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.c43978
1 files changed, 43978 insertions, 0 deletions
diff --git a/src/3rdparty/open62541/open62541.c b/src/3rdparty/open62541/open62541.c
new file mode 100644
index 0000000..217137a
--- /dev/null
+++ b/src/3rdparty/open62541/open62541.c
@@ -0,0 +1,43978 @@
+/* THIS IS A SINGLE-FILE DISTRIBUTION CONCATENATED FROM THE OPEN62541 SOURCES
+ * visit http://open62541.org/ for information about this software
+ * Git-Revision: v0.3.0
+ */
+
+/*
+ * Copyright (C) 2014-2018 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
+ * License v2.0 as stated in the LICENSE file provided with open62541.
+ *
+ * open62541 is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ * A PARTICULAR PURPOSE.
+ */
+
+#ifndef UA_DYNAMIC_LINKING_EXPORT
+# define UA_DYNAMIC_LINKING_EXPORT
+# define MDNSD_DYNAMIC_LINKING
+#endif
+
+/* Enable POSIX features */
+#if !defined(_XOPEN_SOURCE) && !defined(_WRS_KERNEL)
+# define _XOPEN_SOURCE 600
+#endif
+#ifndef _DEFAULT_SOURCE
+# define _DEFAULT_SOURCE
+#endif
+/* On older systems we need to define _BSD_SOURCE.
+ * _DEFAULT_SOURCE is an alias for that. */
+#ifndef _BSD_SOURCE
+# define _BSD_SOURCE
+#endif
+
+/* Disable security warnings for BSD sockets on MSVC */
+#ifdef _MSC_VER
+# define _CRT_SECURE_NO_WARNINGS
+#endif
+
+#include "open62541.h"
+
+/*********************************** amalgamated original file "/home/jvoe/open62541/deps/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 $ */
+
+/*
+ * Copyright (c) 1991, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)queue.h 8.5 (Berkeley) 8/20/94
+ */
+
+
+/*
+ * This file defines five types of data structures: singly-linked lists,
+ * lists, simple queues, tail queues, and circular queues.
+ *
+ *
+ * A singly-linked list is headed by a single forward pointer. The elements
+ * are singly linked for minimum space and pointer manipulation overhead at
+ * the expense of O(n) removal for arbitrary elements. New elements can be
+ * added to the list after an existing element or at the head of the list.
+ * Elements being removed from the head of the list should use the explicit
+ * macro for this purpose for optimum efficiency. A singly-linked list may
+ * only be traversed in the forward direction. Singly-linked lists are ideal
+ * for applications with large datasets and few or no removals or for
+ * implementing a LIFO queue.
+ *
+ * A list is headed by a single forward pointer (or an array of forward
+ * pointers for a hash table header). The elements are doubly linked
+ * so that an arbitrary element can be removed without a need to
+ * traverse the list. New elements can be added to the list before
+ * or after an existing element or at the head of the list. A list
+ * may only be traversed in the forward direction.
+ *
+ * A simple queue is headed by a pair of pointers, one the head of the
+ * list and the other to the tail of the list. The elements are singly
+ * linked to save space, so elements can only be removed from the
+ * head of the list. New elements can be added to the list before or after
+ * an existing element, at the head of the list, or at the end of the
+ * list. A simple queue may only be traversed in the forward direction.
+ *
+ * A tail queue is headed by a pair of pointers, one to the head of the
+ * list and the other to the tail of the list. The elements are doubly
+ * linked so that an arbitrary element can be removed without a need to
+ * traverse the list. New elements can be added to the list before or
+ * after an existing element, at the head of the list, or at the end of
+ * the list. A tail queue may be traversed in either direction.
+ *
+ * A circle queue is headed by a pair of pointers, one to the head of the
+ * list and the other to the tail of the list. The elements are doubly
+ * linked so that an arbitrary element can be removed without a need to
+ * traverse the list. New elements can be added to the list before or after
+ * an existing element, at the head of the list, or at the end of the list.
+ * A circle queue may be traversed in either direction, but has a more
+ * complex end of list detection.
+ *
+ * For details on the use of these macros, see the queue(3) manual page.
+ */
+
+#if defined(QUEUE_MACRO_DEBUG) || (defined(_KERNEL) && defined(DIAGNOSTIC))
+#define _Q_INVALIDATE(a) (a) = ((void *)-1)
+#else
+#define _Q_INVALIDATE(a)
+#endif
+
+/*
+ * Singly-linked List definitions.
+ */
+#define SLIST_HEAD(name, type) \
+struct name { \
+ struct type *slh_first; /* first element */ \
+}
+
+#define SLIST_HEAD_INITIALIZER(head) \
+ { NULL }
+
+/* Fix redefinition of SLIST_ENTRY on mingw winnt.h */
+# ifdef SLIST_ENTRY
+# undef SLIST_ENTRY
+# endif
+
+#define SLIST_ENTRY(type) \
+struct { \
+ struct type *sle_next; /* next element */ \
+}
+
+/*
+ * Singly-linked List access methods.
+ */
+#define SLIST_FIRST(head) ((head)->slh_first)
+#define SLIST_END(head) NULL
+#define SLIST_EMPTY(head) (SLIST_FIRST(head) == SLIST_END(head))
+#define SLIST_NEXT(elm, field) ((elm)->field.sle_next)
+
+#define SLIST_FOREACH(var, head, field) \
+ for((var) = SLIST_FIRST(head); \
+ (var) != SLIST_END(head); \
+ (var) = SLIST_NEXT(var, field))
+
+#define SLIST_FOREACH_SAFE(var, head, field, tvar) \
+ for ((var) = SLIST_FIRST(head); \
+ (var) && ((tvar) = SLIST_NEXT(var, field), 1); \
+ (var) = (tvar))
+
+/*
+ * Singly-linked List functions.
+ */
+#define SLIST_INIT(head) { \
+ SLIST_FIRST(head) = SLIST_END(head); \
+}
+
+#define SLIST_INSERT_AFTER(slistelm, elm, field) do { \
+ (elm)->field.sle_next = (slistelm)->field.sle_next; \
+ (slistelm)->field.sle_next = (elm); \
+} while (0)
+
+#define SLIST_INSERT_HEAD(head, elm, field) do { \
+ (elm)->field.sle_next = (head)->slh_first; \
+ (head)->slh_first = (elm); \
+} while (0)
+
+#define SLIST_REMOVE_AFTER(elm, field) do { \
+ (elm)->field.sle_next = (elm)->field.sle_next->field.sle_next; \
+} while (0)
+
+#define SLIST_REMOVE_HEAD(head, field) do { \
+ (head)->slh_first = (head)->slh_first->field.sle_next; \
+} while (0)
+
+#define SLIST_REMOVE(head, elm, type, field) do { \
+ if ((head)->slh_first == (elm)) { \
+ SLIST_REMOVE_HEAD((head), field); \
+ } else { \
+ struct type *curelm = (head)->slh_first; \
+ \
+ while (curelm->field.sle_next != (elm)) \
+ curelm = curelm->field.sle_next; \
+ curelm->field.sle_next = \
+ curelm->field.sle_next->field.sle_next; \
+ _Q_INVALIDATE((elm)->field.sle_next); \
+ } \
+} while (0)
+
+/*
+ * List definitions.
+ */
+#define LIST_HEAD(name, type) \
+struct name { \
+ struct type *lh_first; /* first element */ \
+}
+
+#define LIST_HEAD_INITIALIZER(head) \
+ { NULL }
+
+#define LIST_ENTRY(type) \
+struct { \
+ struct type *le_next; /* next element */ \
+ struct type **le_prev; /* address of previous next element */ \
+}
+
+/*
+ * List access methods
+ */
+#define LIST_FIRST(head) ((head)->lh_first)
+#define LIST_END(head) NULL
+#define LIST_EMPTY(head) (LIST_FIRST(head) == LIST_END(head))
+#define LIST_NEXT(elm, field) ((elm)->field.le_next)
+
+#define LIST_FOREACH(var, head, field) \
+ for((var) = LIST_FIRST(head); \
+ (var)!= LIST_END(head); \
+ (var) = LIST_NEXT(var, field))
+
+#define LIST_FOREACH_SAFE(var, head, field, tvar) \
+ for ((var) = LIST_FIRST(head); \
+ (var) && ((tvar) = LIST_NEXT(var, field), 1); \
+ (var) = (tvar))
+
+/*
+ * List functions.
+ */
+#define LIST_INIT(head) do { \
+ LIST_FIRST(head) = LIST_END(head); \
+} while (0)
+
+#define LIST_INSERT_AFTER(listelm, elm, field) do { \
+ if (((elm)->field.le_next = (listelm)->field.le_next) != NULL) \
+ (listelm)->field.le_next->field.le_prev = \
+ &(elm)->field.le_next; \
+ (listelm)->field.le_next = (elm); \
+ (elm)->field.le_prev = &(listelm)->field.le_next; \
+} while (0)
+
+#define LIST_INSERT_BEFORE(listelm, elm, field) do { \
+ (elm)->field.le_prev = (listelm)->field.le_prev; \
+ (elm)->field.le_next = (listelm); \
+ *(listelm)->field.le_prev = (elm); \
+ (listelm)->field.le_prev = &(elm)->field.le_next; \
+} while (0)
+
+#define LIST_INSERT_HEAD(head, elm, field) do { \
+ if (((elm)->field.le_next = (head)->lh_first) != NULL) \
+ (head)->lh_first->field.le_prev = &(elm)->field.le_next;\
+ (head)->lh_first = (elm); \
+ (elm)->field.le_prev = &(head)->lh_first; \
+} while (0)
+
+#define LIST_REMOVE(elm, field) do { \
+ if ((elm)->field.le_next != NULL) \
+ (elm)->field.le_next->field.le_prev = \
+ (elm)->field.le_prev; \
+ *(elm)->field.le_prev = (elm)->field.le_next; \
+ _Q_INVALIDATE((elm)->field.le_prev); \
+ _Q_INVALIDATE((elm)->field.le_next); \
+} while (0)
+
+#define LIST_REPLACE(elm, elm2, field) do { \
+ if (((elm2)->field.le_next = (elm)->field.le_next) != NULL) \
+ (elm2)->field.le_next->field.le_prev = \
+ &(elm2)->field.le_next; \
+ (elm2)->field.le_prev = (elm)->field.le_prev; \
+ *(elm2)->field.le_prev = (elm2); \
+ _Q_INVALIDATE((elm)->field.le_prev); \
+ _Q_INVALIDATE((elm)->field.le_next); \
+} while (0)
+
+/*
+ * Simple queue definitions.
+ */
+#define SIMPLEQ_HEAD(name, type) \
+struct name { \
+ struct type *sqh_first; /* first element */ \
+ struct type **sqh_last; /* addr of last next element */ \
+}
+
+#define SIMPLEQ_HEAD_INITIALIZER(head) \
+ { NULL, &(head).sqh_first }
+
+#define SIMPLEQ_ENTRY(type) \
+struct { \
+ struct type *sqe_next; /* next element */ \
+}
+
+/*
+ * Simple queue access methods.
+ */
+#define SIMPLEQ_FIRST(head) ((head)->sqh_first)
+#define SIMPLEQ_END(head) NULL
+#define SIMPLEQ_EMPTY(head) (SIMPLEQ_FIRST(head) == SIMPLEQ_END(head))
+#define SIMPLEQ_NEXT(elm, field) ((elm)->field.sqe_next)
+
+#define SIMPLEQ_FOREACH(var, head, field) \
+ for((var) = SIMPLEQ_FIRST(head); \
+ (var) != SIMPLEQ_END(head); \
+ (var) = SIMPLEQ_NEXT(var, field))
+
+#define SIMPLEQ_FOREACH_SAFE(var, head, field, tvar) \
+ for ((var) = SIMPLEQ_FIRST(head); \
+ (var) && ((tvar) = SIMPLEQ_NEXT(var, field), 1); \
+ (var) = (tvar))
+
+/*
+ * Simple queue functions.
+ */
+#define SIMPLEQ_INIT(head) do { \
+ (head)->sqh_first = NULL; \
+ (head)->sqh_last = &(head)->sqh_first; \
+} while (0)
+
+#define SIMPLEQ_INSERT_HEAD(head, elm, field) do { \
+ if (((elm)->field.sqe_next = (head)->sqh_first) == NULL) \
+ (head)->sqh_last = &(elm)->field.sqe_next; \
+ (head)->sqh_first = (elm); \
+} while (0)
+
+#define SIMPLEQ_INSERT_TAIL(head, elm, field) do { \
+ (elm)->field.sqe_next = NULL; \
+ *(head)->sqh_last = (elm); \
+ (head)->sqh_last = &(elm)->field.sqe_next; \
+} while (0)
+
+#define SIMPLEQ_INSERT_AFTER(head, listelm, elm, field) do { \
+ if (((elm)->field.sqe_next = (listelm)->field.sqe_next) == NULL)\
+ (head)->sqh_last = &(elm)->field.sqe_next; \
+ (listelm)->field.sqe_next = (elm); \
+} while (0)
+
+#define SIMPLEQ_REMOVE_HEAD(head, field) do { \
+ if (((head)->sqh_first = (head)->sqh_first->field.sqe_next) == NULL) \
+ (head)->sqh_last = &(head)->sqh_first; \
+} while (0)
+
+#define SIMPLEQ_REMOVE_AFTER(head, elm, field) do { \
+ if (((elm)->field.sqe_next = (elm)->field.sqe_next->field.sqe_next) \
+ == NULL) \
+ (head)->sqh_last = &(elm)->field.sqe_next; \
+} while (0)
+
+/*
+ * XOR Simple queue definitions.
+ */
+#define XSIMPLEQ_HEAD(name, type) \
+struct name { \
+ struct type *sqx_first; /* first element */ \
+ struct type **sqx_last; /* addr of last next element */ \
+ unsigned long sqx_cookie; \
+}
+
+#define XSIMPLEQ_ENTRY(type) \
+struct { \
+ struct type *sqx_next; /* next element */ \
+}
+
+/*
+ * XOR Simple queue access methods.
+ */
+#define XSIMPLEQ_XOR(head, ptr) ((__typeof(ptr))((head)->sqx_cookie ^ \
+ (unsigned long)(ptr)))
+#define XSIMPLEQ_FIRST(head) XSIMPLEQ_XOR(head, ((head)->sqx_first))
+#define XSIMPLEQ_END(head) NULL
+#define XSIMPLEQ_EMPTY(head) (XSIMPLEQ_FIRST(head) == XSIMPLEQ_END(head))
+#define XSIMPLEQ_NEXT(head, elm, field) XSIMPLEQ_XOR(head, ((elm)->field.sqx_next))
+
+
+#define XSIMPLEQ_FOREACH(var, head, field) \
+ for ((var) = XSIMPLEQ_FIRST(head); \
+ (var) != XSIMPLEQ_END(head); \
+ (var) = XSIMPLEQ_NEXT(head, var, field))
+
+#define XSIMPLEQ_FOREACH_SAFE(var, head, field, tvar) \
+ for ((var) = XSIMPLEQ_FIRST(head); \
+ (var) && ((tvar) = XSIMPLEQ_NEXT(head, var, field), 1); \
+ (var) = (tvar))
+
+/*
+ * XOR Simple queue functions.
+ */
+#define XSIMPLEQ_INIT(head) do { \
+ arc4random_buf(&(head)->sqx_cookie, sizeof((head)->sqx_cookie)); \
+ (head)->sqx_first = XSIMPLEQ_XOR(head, NULL); \
+ (head)->sqx_last = XSIMPLEQ_XOR(head, &(head)->sqx_first); \
+} while (0)
+
+#define XSIMPLEQ_INSERT_HEAD(head, elm, field) do { \
+ if (((elm)->field.sqx_next = (head)->sqx_first) == \
+ XSIMPLEQ_XOR(head, NULL)) \
+ (head)->sqx_last = XSIMPLEQ_XOR(head, &(elm)->field.sqx_next); \
+ (head)->sqx_first = XSIMPLEQ_XOR(head, (elm)); \
+} while (0)
+
+#define XSIMPLEQ_INSERT_TAIL(head, elm, field) do { \
+ (elm)->field.sqx_next = XSIMPLEQ_XOR(head, NULL); \
+ *(XSIMPLEQ_XOR(head, (head)->sqx_last)) = XSIMPLEQ_XOR(head, (elm)); \
+ (head)->sqx_last = XSIMPLEQ_XOR(head, &(elm)->field.sqx_next); \
+} while (0)
+
+#define XSIMPLEQ_INSERT_AFTER(head, listelm, elm, field) do { \
+ if (((elm)->field.sqx_next = (listelm)->field.sqx_next) == \
+ XSIMPLEQ_XOR(head, NULL)) \
+ (head)->sqx_last = XSIMPLEQ_XOR(head, &(elm)->field.sqx_next); \
+ (listelm)->field.sqx_next = XSIMPLEQ_XOR(head, (elm)); \
+} while (0)
+
+#define XSIMPLEQ_REMOVE_HEAD(head, field) do { \
+ if (((head)->sqx_first = XSIMPLEQ_XOR(head, \
+ (head)->sqx_first)->field.sqx_next) == XSIMPLEQ_XOR(head, NULL)) \
+ (head)->sqx_last = XSIMPLEQ_XOR(head, &(head)->sqx_first); \
+} while (0)
+
+#define XSIMPLEQ_REMOVE_AFTER(head, elm, field) do { \
+ if (((elm)->field.sqx_next = XSIMPLEQ_XOR(head, \
+ (elm)->field.sqx_next)->field.sqx_next) \
+ == XSIMPLEQ_XOR(head, NULL)) \
+ (head)->sqx_last = \
+ XSIMPLEQ_XOR(head, &(elm)->field.sqx_next); \
+} while (0)
+
+
+/*
+ * Tail queue definitions.
+ */
+#define TAILQ_HEAD(name, type) \
+struct name { \
+ struct type *tqh_first; /* first element */ \
+ struct type **tqh_last; /* addr of last next element */ \
+}
+
+#define TAILQ_HEAD_INITIALIZER(head) \
+ { NULL, &(head).tqh_first }
+
+#define TAILQ_ENTRY(type) \
+struct { \
+ struct type *tqe_next; /* next element */ \
+ struct type **tqe_prev; /* address of previous next element */ \
+}
+
+/*
+ * tail queue access methods
+ */
+#define TAILQ_FIRST(head) ((head)->tqh_first)
+#define TAILQ_END(head) NULL
+#define TAILQ_NEXT(elm, field) ((elm)->field.tqe_next)
+#define TAILQ_LAST(head, headname) \
+ (*(((struct headname *)((head)->tqh_last))->tqh_last))
+/* XXX */
+#define TAILQ_PREV(elm, headname, field) \
+ (*(((struct headname *)((elm)->field.tqe_prev))->tqh_last))
+#define TAILQ_EMPTY(head) \
+ (TAILQ_FIRST(head) == TAILQ_END(head))
+
+#define TAILQ_FOREACH(var, head, field) \
+ for((var) = TAILQ_FIRST(head); \
+ (var) != TAILQ_END(head); \
+ (var) = TAILQ_NEXT(var, field))
+
+#define TAILQ_FOREACH_SAFE(var, head, field, tvar) \
+ for ((var) = TAILQ_FIRST(head); \
+ (var) != TAILQ_END(head) && \
+ ((tvar) = TAILQ_NEXT(var, field), 1); \
+ (var) = (tvar))
+
+
+#define TAILQ_FOREACH_REVERSE(var, head, headname, field) \
+ for((var) = TAILQ_LAST(head, headname); \
+ (var) != TAILQ_END(head); \
+ (var) = TAILQ_PREV(var, headname, field))
+
+#define TAILQ_FOREACH_REVERSE_SAFE(var, head, headname, field, tvar) \
+ for ((var) = TAILQ_LAST(head, headname); \
+ (var) != TAILQ_END(head) && \
+ ((tvar) = TAILQ_PREV(var, headname, field), 1); \
+ (var) = (tvar))
+
+/*
+ * Tail queue functions.
+ */
+#define TAILQ_INIT(head) do { \
+ (head)->tqh_first = NULL; \
+ (head)->tqh_last = &(head)->tqh_first; \
+} while (0)
+
+#define TAILQ_INSERT_HEAD(head, elm, field) do { \
+ if (((elm)->field.tqe_next = (head)->tqh_first) != NULL) \
+ (head)->tqh_first->field.tqe_prev = \
+ &(elm)->field.tqe_next; \
+ else \
+ (head)->tqh_last = &(elm)->field.tqe_next; \
+ (head)->tqh_first = (elm); \
+ (elm)->field.tqe_prev = &(head)->tqh_first; \
+} while (0)
+
+#define TAILQ_INSERT_TAIL(head, elm, field) do { \
+ (elm)->field.tqe_next = NULL; \
+ (elm)->field.tqe_prev = (head)->tqh_last; \
+ *(head)->tqh_last = (elm); \
+ (head)->tqh_last = &(elm)->field.tqe_next; \
+} while (0)
+
+#define TAILQ_INSERT_AFTER(head, listelm, elm, field) do { \
+ if (((elm)->field.tqe_next = (listelm)->field.tqe_next) != NULL)\
+ (elm)->field.tqe_next->field.tqe_prev = \
+ &(elm)->field.tqe_next; \
+ else \
+ (head)->tqh_last = &(elm)->field.tqe_next; \
+ (listelm)->field.tqe_next = (elm); \
+ (elm)->field.tqe_prev = &(listelm)->field.tqe_next; \
+} while (0)
+
+#define TAILQ_INSERT_BEFORE(listelm, elm, field) do { \
+ (elm)->field.tqe_prev = (listelm)->field.tqe_prev; \
+ (elm)->field.tqe_next = (listelm); \
+ *(listelm)->field.tqe_prev = (elm); \
+ (listelm)->field.tqe_prev = &(elm)->field.tqe_next; \
+} while (0)
+
+#define TAILQ_REMOVE(head, elm, field) do { \
+ if (((elm)->field.tqe_next) != NULL) \
+ (elm)->field.tqe_next->field.tqe_prev = \
+ (elm)->field.tqe_prev; \
+ else \
+ (head)->tqh_last = (elm)->field.tqe_prev; \
+ *(elm)->field.tqe_prev = (elm)->field.tqe_next; \
+ _Q_INVALIDATE((elm)->field.tqe_prev); \
+ _Q_INVALIDATE((elm)->field.tqe_next); \
+} while (0)
+
+#define TAILQ_REPLACE(head, elm, elm2, field) do { \
+ if (((elm2)->field.tqe_next = (elm)->field.tqe_next) != NULL) \
+ (elm2)->field.tqe_next->field.tqe_prev = \
+ &(elm2)->field.tqe_next; \
+ else \
+ (head)->tqh_last = &(elm2)->field.tqe_next; \
+ (elm2)->field.tqe_prev = (elm)->field.tqe_prev; \
+ *(elm2)->field.tqe_prev = (elm2); \
+ _Q_INVALIDATE((elm)->field.tqe_prev); \
+ _Q_INVALIDATE((elm)->field.tqe_next); \
+} while (0)
+
+/*
+ * Circular queue definitions.
+ */
+#define CIRCLEQ_HEAD(name, type) \
+struct name { \
+ struct type *cqh_first; /* first element */ \
+ struct type *cqh_last; /* last element */ \
+}
+
+#define CIRCLEQ_HEAD_INITIALIZER(head) \
+ { CIRCLEQ_END(&head), CIRCLEQ_END(&head) }
+
+#define CIRCLEQ_ENTRY(type) \
+struct { \
+ struct type *cqe_next; /* next element */ \
+ struct type *cqe_prev; /* previous element */ \
+}
+
+/*
+ * Circular queue access methods
+ */
+#define CIRCLEQ_FIRST(head) ((head)->cqh_first)
+#define CIRCLEQ_LAST(head) ((head)->cqh_last)
+#define CIRCLEQ_END(head) ((void *)(head))
+#define CIRCLEQ_NEXT(elm, field) ((elm)->field.cqe_next)
+#define CIRCLEQ_PREV(elm, field) ((elm)->field.cqe_prev)
+#define CIRCLEQ_EMPTY(head) \
+ (CIRCLEQ_FIRST(head) == CIRCLEQ_END(head))
+
+#define CIRCLEQ_FOREACH(var, head, field) \
+ for((var) = CIRCLEQ_FIRST(head); \
+ (var) != CIRCLEQ_END(head); \
+ (var) = CIRCLEQ_NEXT(var, field))
+
+#define CIRCLEQ_FOREACH_SAFE(var, head, field, tvar) \
+ for ((var) = CIRCLEQ_FIRST(head); \
+ (var) != CIRCLEQ_END(head) && \
+ ((tvar) = CIRCLEQ_NEXT(var, field), 1); \
+ (var) = (tvar))
+
+#define CIRCLEQ_FOREACH_REVERSE(var, head, field) \
+ for((var) = CIRCLEQ_LAST(head); \
+ (var) != CIRCLEQ_END(head); \
+ (var) = CIRCLEQ_PREV(var, field))
+
+#define CIRCLEQ_FOREACH_REVERSE_SAFE(var, head, headname, field, tvar) \
+ for ((var) = CIRCLEQ_LAST(head, headname); \
+ (var) != CIRCLEQ_END(head) && \
+ ((tvar) = CIRCLEQ_PREV(var, headname, field), 1); \
+ (var) = (tvar))
+
+/*
+ * Circular queue functions.
+ */
+#define CIRCLEQ_INIT(head) do { \
+ (head)->cqh_first = CIRCLEQ_END(head); \
+ (head)->cqh_last = CIRCLEQ_END(head); \
+} while (0)
+
+#define CIRCLEQ_INSERT_AFTER(head, listelm, elm, field) do { \
+ (elm)->field.cqe_next = (listelm)->field.cqe_next; \
+ (elm)->field.cqe_prev = (listelm); \
+ if ((listelm)->field.cqe_next == CIRCLEQ_END(head)) \
+ (head)->cqh_last = (elm); \
+ else \
+ (listelm)->field.cqe_next->field.cqe_prev = (elm); \
+ (listelm)->field.cqe_next = (elm); \
+} while (0)
+
+#define CIRCLEQ_INSERT_BEFORE(head, listelm, elm, field) do { \
+ (elm)->field.cqe_next = (listelm); \
+ (elm)->field.cqe_prev = (listelm)->field.cqe_prev; \
+ if ((listelm)->field.cqe_prev == CIRCLEQ_END(head)) \
+ (head)->cqh_first = (elm); \
+ else \
+ (listelm)->field.cqe_prev->field.cqe_next = (elm); \
+ (listelm)->field.cqe_prev = (elm); \
+} while (0)
+
+#define CIRCLEQ_INSERT_HEAD(head, elm, field) do { \
+ (elm)->field.cqe_next = (head)->cqh_first; \
+ (elm)->field.cqe_prev = CIRCLEQ_END(head); \
+ if ((head)->cqh_last == CIRCLEQ_END(head)) \
+ (head)->cqh_last = (elm); \
+ else \
+ (head)->cqh_first->field.cqe_prev = (elm); \
+ (head)->cqh_first = (elm); \
+} while (0)
+
+#define CIRCLEQ_INSERT_TAIL(head, elm, field) do { \
+ (elm)->field.cqe_next = CIRCLEQ_END(head); \
+ (elm)->field.cqe_prev = (head)->cqh_last; \
+ if ((head)->cqh_first == CIRCLEQ_END(head)) \
+ (head)->cqh_first = (elm); \
+ else \
+ (head)->cqh_last->field.cqe_next = (elm); \
+ (head)->cqh_last = (elm); \
+} while (0)
+
+#define CIRCLEQ_REMOVE(head, elm, field) do { \
+ if ((elm)->field.cqe_next == CIRCLEQ_END(head)) \
+ (head)->cqh_last = (elm)->field.cqe_prev; \
+ else \
+ (elm)->field.cqe_next->field.cqe_prev = \
+ (elm)->field.cqe_prev; \
+ if ((elm)->field.cqe_prev == CIRCLEQ_END(head)) \
+ (head)->cqh_first = (elm)->field.cqe_next; \
+ else \
+ (elm)->field.cqe_prev->field.cqe_next = \
+ (elm)->field.cqe_next; \
+ _Q_INVALIDATE((elm)->field.cqe_prev); \
+ _Q_INVALIDATE((elm)->field.cqe_next); \
+} while (0)
+
+#define CIRCLEQ_REPLACE(head, elm, elm2, field) do { \
+ if (((elm2)->field.cqe_next = (elm)->field.cqe_next) == \
+ CIRCLEQ_END(head)) \
+ (head)->cqh_last = (elm2); \
+ else \
+ (elm2)->field.cqe_next->field.cqe_prev = (elm2); \
+ if (((elm2)->field.cqe_prev = (elm)->field.cqe_prev) == \
+ CIRCLEQ_END(head)) \
+ (head)->cqh_first = (elm2); \
+ else \
+ (elm2)->field.cqe_prev->field.cqe_next = (elm2); \
+ _Q_INVALIDATE((elm)->field.cqe_prev); \
+ _Q_INVALIDATE((elm)->field.cqe_next); \
+} while (0)
+
+
+/*********************************** amalgamated original file "/home/jvoe/open62541/deps/pcg_basic.h" ***********************************/
+
+/*
+ * PCG Random Number Generation for C.
+ *
+ * Copyright 2014 Melissa O'Neill <oneill@pcg-random.org>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * For additional information about the PCG random number generation scheme,
+ * including its license and other licensing options, visit
+ *
+ * http://www.pcg-random.org
+ */
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+typedef struct pcg_state_setseq_64 {
+ uint64_t state; /* RNG state. All values are possible. */
+ uint64_t inc; /* Controls which RNG sequence (stream) is selected. Must
+ * *always* be odd. */
+} pcg32_random_t;
+
+#define PCG32_INITIALIZER { 0x853c49e6748fea9bULL, 0xda3e39cb94b95bdbULL }
+
+void pcg32_srandom_r(pcg32_random_t* rng, uint64_t initial_state, uint64_t initseq);
+uint32_t pcg32_random_r(pcg32_random_t* rng);
+
+#ifdef __cplusplus
+}
+#endif
+
+
+/*********************************** amalgamated original file "/home/jvoe/open62541/deps/libc_time.h" ***********************************/
+
+
+struct mytm {
+ int tm_sec;
+ int tm_min;
+ int tm_hour;
+ int tm_mday;
+ int tm_mon;
+ int tm_year;
+ int tm_wday;
+ int tm_yday;
+ int tm_isdst;
+ /* long __tm_gmtoff; */
+ /* const char *__tm_zone; */
+};
+
+int __secs_to_tm(long long t, struct mytm *tm);
+
+
+/*********************************** amalgamated original file "/home/jvoe/open62541/src/ua_util.h" ***********************************/
+
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * Copyright 2014-2017 (c) Julius Pfrommer, Fraunhofer IOSB
+ * Copyright 2014, 2017 (c) Florian Palm
+ * Copyright 2015 (c) LEvertz
+ * Copyright 2015-2016 (c) Sten Grüner
+ * Copyright 2015 (c) Chris Iatrou
+ * Copyright 2015-2016 (c) Oleksiy Vasylyev
+ * Copyright 2017 (c) Stefan Profanter, fortiss GmbH
+ */
+
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* BSD Queue Macros */
+
+/* Macro-Expand for MSVC workarounds */
+#define UA_MACRO_EXPAND(x) x
+
+/* Integer Shortnames
+ * ------------------
+ * These are not exposed on the public API, since many user-applications make
+ * the same definitions in their headers. */
+
+typedef UA_Byte u8;
+typedef UA_SByte i8;
+typedef UA_UInt16 u16;
+typedef UA_Int16 i16;
+typedef UA_UInt32 u32;
+typedef UA_Int32 i32;
+typedef UA_UInt64 u64;
+typedef UA_Int64 i64;
+typedef UA_StatusCode status;
+
+/* Atomic Operations
+ * -----------------
+ * Atomic operations that synchronize across processor cores (for
+ * multithreading). Only the inline-functions defined next are used. Replace
+ * with architecture-specific operations if necessary. */
+#ifndef UA_ENABLE_MULTITHREADING
+# define UA_atomic_sync()
+#else
+# ifdef _MSC_VER /* Visual Studio */
+# define UA_atomic_sync() _ReadWriteBarrier()
+# else /* GCC/Clang */
+# define UA_atomic_sync() __sync_synchronize()
+# endif
+#endif
+
+static UA_INLINE void *
+UA_atomic_xchg(void * volatile * addr, void *newptr) {
+#ifndef UA_ENABLE_MULTITHREADING
+ void *old = *addr;
+ *addr = newptr;
+ return old;
+#else
+# ifdef _MSC_VER /* Visual Studio */
+ return _InterlockedExchangePointer(addr, newptr);
+# else /* GCC/Clang */
+ return __sync_lock_test_and_set(addr, newptr);
+# endif
+#endif
+}
+
+static UA_INLINE void *
+UA_atomic_cmpxchg(void * volatile * addr, void *expected, void *newptr) {
+#ifndef UA_ENABLE_MULTITHREADING
+ void *old = *addr;
+ if(old == expected) {
+ *addr = newptr;
+ }
+ return old;
+#else
+# ifdef _MSC_VER /* Visual Studio */
+ return _InterlockedCompareExchangePointer(addr, expected, newptr);
+# else /* GCC/Clang */
+ return __sync_val_compare_and_swap(addr, expected, newptr);
+# endif
+#endif
+}
+
+static UA_INLINE uint32_t
+UA_atomic_addUInt32(volatile uint32_t *addr, uint32_t increase) {
+#ifndef UA_ENABLE_MULTITHREADING
+ *addr += increase;
+ return *addr;
+#else
+# ifdef _MSC_VER /* Visual Studio */
+ return _InterlockedExchangeAdd(addr, increase) + increase;
+# else /* GCC/Clang */
+ return __sync_add_and_fetch(addr, increase);
+# endif
+#endif
+}
+
+static UA_INLINE size_t
+UA_atomic_addSize(volatile size_t *addr, size_t increase) {
+#ifndef UA_ENABLE_MULTITHREADING
+ *addr += increase;
+ return *addr;
+#else
+# ifdef _MSC_VER /* Visual Studio */
+ return _InterlockedExchangeAdd(addr, increase) + increase;
+# else /* GCC/Clang */
+ return __sync_add_and_fetch(addr, increase);
+# endif
+#endif
+}
+
+static UA_INLINE uint32_t
+UA_atomic_subUInt32(volatile uint32_t *addr, uint32_t decrease) {
+#ifndef UA_ENABLE_MULTITHREADING
+ *addr -= decrease;
+ return *addr;
+#else
+# ifdef _MSC_VER /* Visual Studio */
+ return _InterlockedExchangeSub(addr, decrease) - decrease;
+# else /* GCC/Clang */
+ return __sync_sub_and_fetch(addr, decrease);
+# endif
+#endif
+}
+
+static UA_INLINE size_t
+UA_atomic_subSize(volatile size_t *addr, size_t decrease) {
+#ifndef UA_ENABLE_MULTITHREADING
+ *addr -= decrease;
+ return *addr;
+#else
+# ifdef _MSC_VER /* Visual Studio */
+ return _InterlockedExchangeSub(addr, decrease) - decrease;
+# else /* GCC/Clang */
+ return __sync_sub_and_fetch(addr, decrease);
+# endif
+#endif
+}
+
+/* Utility Functions
+ * ----------------- */
+
+/* Convert given byte string to a positive number. Returns the number of valid
+ * digits. Stops if a non-digit char is found and returns the number of digits
+ * up to that point. */
+size_t UA_readNumber(u8 *buf, size_t buflen, u32 *number);
+
+#define UA_MIN(A,B) (A > B ? B : A)
+#define UA_MAX(A,B) (A > B ? A : B)
+
+#ifdef UA_DEBUG_DUMP_PKGS
+void UA_EXPORT UA_dump_hex_pkg(UA_Byte* buffer, size_t bufferLen);
+#endif
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+
+/*********************************** amalgamated original file "/home/jvoe/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) Julius Pfrommer, Fraunhofer IOSB
+ * 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
+ */
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+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, size_t customTypesSize,
+ const UA_DataType *customTypes) UA_FUNC_ATTR_WARN_UNUSED_RESULT;
+
+/* 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(void *p, const UA_DataType *type);
+
+const UA_DataType *
+UA_findDataTypeByBinary(const UA_NodeId *typeId);
+
+#ifdef __cplusplus
+}
+#endif
+
+
+/*********************************** amalgamated original file "/home/jvoe/open62541/build/src_generated/ua_types_generated_encoding_binary.h" ***********************************/
+
+/* Generated from Opc.Ua.Types.bsd with script /home/jvoe/open62541/tools/generate_datatypes.py
+ * on host rigel by user jvoe at 2019-01-04 01:18:40 */
+
+
+/* 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], 0, NULL);
+}
+
+/* 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], 0, NULL);
+}
+
+/* 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], 0, NULL);
+}
+
+/* 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], 0, NULL);
+}
+
+/* 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], 0, NULL);
+}
+
+/* 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], 0, NULL);
+}
+
+/* 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], 0, NULL);
+}
+
+/* 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], 0, NULL);
+}
+
+/* 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], 0, NULL);
+}
+
+/* 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], 0, NULL);
+}
+
+/* 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], 0, NULL);
+}
+
+/* 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], 0, NULL);
+}
+
+/* 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], 0, NULL);
+}
+
+/* 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], 0, NULL);
+}
+
+/* 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], 0, NULL);
+}
+
+/* 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], 0, NULL);
+}
+
+/* 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], 0, NULL);
+}
+
+/* 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], 0, NULL);
+}
+
+/* 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], 0, NULL);
+}
+
+/* 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], 0, NULL);
+}
+
+/* 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], 0, NULL);
+}
+
+/* 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], 0, NULL);
+}
+
+/* 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], 0, NULL);
+}
+
+/* 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], 0, NULL);
+}
+
+/* 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], 0, NULL);
+}
+
+/* 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], 0, NULL);
+}
+
+/* SemanticChangeStructureDataType */
+static UA_INLINE UA_StatusCode
+UA_SemanticChangeStructureDataType_encodeBinary(const UA_SemanticChangeStructureDataType *src, UA_Byte **bufPos, const UA_Byte **bufEnd) {
+ return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_SEMANTICCHANGESTRUCTUREDATATYPE], bufPos, bufEnd, NULL, NULL);
+}
+static UA_INLINE UA_StatusCode
+UA_SemanticChangeStructureDataType_decodeBinary(const UA_ByteString *src, size_t *offset, UA_SemanticChangeStructureDataType *dst) {
+ return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_SEMANTICCHANGESTRUCTUREDATATYPE], 0, NULL);
+}
+
+/* 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], 0, NULL);
+}
+
+/* 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], 0, NULL);
+}
+
+/* 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], 0, NULL);
+}
+
+/* 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], 0, NULL);
+}
+
+/* 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], 0, NULL);
+}
+
+/* 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], 0, NULL);
+}
+
+/* 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], 0, NULL);
+}
+
+/* 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], 0, NULL);
+}
+
+/* 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], 0, NULL);
+}
+
+/* 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], 0, NULL);
+}
+
+/* FindServersOnNetworkRequest */
+static UA_INLINE UA_StatusCode
+UA_FindServersOnNetworkRequest_encodeBinary(const UA_FindServersOnNetworkRequest *src, UA_Byte **bufPos, const UA_Byte **bufEnd) {
+ return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_FINDSERVERSONNETWORKREQUEST], bufPos, bufEnd, NULL, NULL);
+}
+static UA_INLINE UA_StatusCode
+UA_FindServersOnNetworkRequest_decodeBinary(const UA_ByteString *src, size_t *offset, UA_FindServersOnNetworkRequest *dst) {
+ return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_FINDSERVERSONNETWORKREQUEST], 0, NULL);
+}
+
+/* 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], 0, NULL);
+}
+
+/* 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], 0, NULL);
+}
+
+/* MdnsDiscoveryConfiguration */
+static UA_INLINE UA_StatusCode
+UA_MdnsDiscoveryConfiguration_encodeBinary(const UA_MdnsDiscoveryConfiguration *src, UA_Byte **bufPos, const UA_Byte **bufEnd) {
+ return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_MDNSDISCOVERYCONFIGURATION], bufPos, bufEnd, NULL, NULL);
+}
+static UA_INLINE UA_StatusCode
+UA_MdnsDiscoveryConfiguration_decodeBinary(const UA_ByteString *src, size_t *offset, UA_MdnsDiscoveryConfiguration *dst) {
+ return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_MDNSDISCOVERYCONFIGURATION], 0, NULL);
+}
+
+/* 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], 0, NULL);
+}
+
+/* ParsingResult */
+static UA_INLINE UA_StatusCode
+UA_ParsingResult_encodeBinary(const UA_ParsingResult *src, UA_Byte **bufPos, const UA_Byte **bufEnd) {
+ return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_PARSINGRESULT], bufPos, bufEnd, NULL, NULL);
+}
+static UA_INLINE UA_StatusCode
+UA_ParsingResult_decodeBinary(const UA_ByteString *src, size_t *offset, UA_ParsingResult *dst) {
+ return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_PARSINGRESULT], 0, NULL);
+}
+
+/* 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], 0, NULL);
+}
+
+/* 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], 0, NULL);
+}
+
+/* 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], 0, NULL);
+}
+
+/* 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], 0, NULL);
+}
+
+/* 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], 0, NULL);
+}
+
+/* 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], 0, NULL);
+}
+
+/* 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], 0, NULL);
+}
+
+/* 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], 0, NULL);
+}
+
+/* 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], 0, NULL);
+}
+
+/* QueryDataSet */
+static UA_INLINE UA_StatusCode
+UA_QueryDataSet_encodeBinary(const UA_QueryDataSet *src, UA_Byte **bufPos, const UA_Byte **bufEnd) {
+ return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_QUERYDATASET], bufPos, bufEnd, NULL, NULL);
+}
+static UA_INLINE UA_StatusCode
+UA_QueryDataSet_decodeBinary(const UA_ByteString *src, size_t *offset, UA_QueryDataSet *dst) {
+ return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_QUERYDATASET], 0, NULL);
+}
+
+/* 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], 0, NULL);
+}
+
+/* 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], 0, NULL);
+}
+
+/* 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], 0, NULL);
+}
+
+/* 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], 0, NULL);
+}
+
+/* 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], 0, NULL);
+}
+
+/* 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], 0, NULL);
+}
+
+/* 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], 0, NULL);
+}
+
+/* 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], 0, NULL);
+}
+
+/* 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], 0, NULL);
+}
+
+/* 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], 0, NULL);
+}
+
+/* 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], 0, NULL);
+}
+
+/* ReferenceNode */
+static UA_INLINE UA_StatusCode
+UA_ReferenceNode_encodeBinary(const UA_ReferenceNode *src, UA_Byte **bufPos, const UA_Byte **bufEnd) {
+ return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_REFERENCENODE], bufPos, bufEnd, NULL, NULL);
+}
+static UA_INLINE UA_StatusCode
+UA_ReferenceNode_decodeBinary(const UA_ByteString *src, size_t *offset, UA_ReferenceNode *dst) {
+ return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_REFERENCENODE], 0, NULL);
+}
+
+/* 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], 0, NULL);
+}
+
+/* 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], 0, NULL);
+}
+
+/* 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], 0, NULL);
+}
+
+/* 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], 0, NULL);
+}
+
+/* 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], 0, NULL);
+}
+
+/* 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], 0, NULL);
+}
+
+/* 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], 0, NULL);
+}
+
+/* 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], 0, NULL);
+}
+
+/* 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], 0, NULL);
+}
+
+/* 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], 0, NULL);
+}
+
+/* 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], 0, NULL);
+}
+
+/* SubscriptionDiagnosticsDataType */
+static UA_INLINE UA_StatusCode
+UA_SubscriptionDiagnosticsDataType_encodeBinary(const UA_SubscriptionDiagnosticsDataType *src, UA_Byte **bufPos, const UA_Byte **bufEnd) {
+ return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_SUBSCRIPTIONDIAGNOSTICSDATATYPE], bufPos, bufEnd, NULL, NULL);
+}
+static UA_INLINE UA_StatusCode
+UA_SubscriptionDiagnosticsDataType_decodeBinary(const UA_ByteString *src, size_t *offset, UA_SubscriptionDiagnosticsDataType *dst) {
+ return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_SUBSCRIPTIONDIAGNOSTICSDATATYPE], 0, NULL);
+}
+
+/* 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], 0, NULL);
+}
+
+/* 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], 0, NULL);
+}
+
+/* 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], 0, NULL);
+}
+
+/* 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], 0, NULL);
+}
+
+/* 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], 0, NULL);
+}
+
+/* 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], 0, NULL);
+}
+
+/* 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], 0, NULL);
+}
+
+/* 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], 0, NULL);
+}
+
+/* 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], 0, NULL);
+}
+
+/* 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], 0, NULL);
+}
+
+/* ServerOnNetwork */
+static UA_INLINE UA_StatusCode
+UA_ServerOnNetwork_encodeBinary(const UA_ServerOnNetwork *src, UA_Byte **bufPos, const UA_Byte **bufEnd) {
+ return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_SERVERONNETWORK], bufPos, bufEnd, NULL, NULL);
+}
+static UA_INLINE UA_StatusCode
+UA_ServerOnNetwork_decodeBinary(const UA_ByteString *src, size_t *offset, UA_ServerOnNetwork *dst) {
+ return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_SERVERONNETWORK], 0, NULL);
+}
+
+/* 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], 0, NULL);
+}
+
+/* FindServersOnNetworkResponse */
+static UA_INLINE UA_StatusCode
+UA_FindServersOnNetworkResponse_encodeBinary(const UA_FindServersOnNetworkResponse *src, UA_Byte **bufPos, const UA_Byte **bufEnd) {
+ return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_FINDSERVERSONNETWORKRESPONSE], bufPos, bufEnd, NULL, NULL);
+}
+static UA_INLINE UA_StatusCode
+UA_FindServersOnNetworkResponse_decodeBinary(const UA_ByteString *src, size_t *offset, UA_FindServersOnNetworkResponse *dst) {
+ return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_FINDSERVERSONNETWORKRESPONSE], 0, NULL);
+}
+
+/* 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], 0, NULL);
+}
+
+/* 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], 0, NULL);
+}
+
+/* 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], 0, NULL);
+}
+
+/* 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], 0, NULL);
+}
+
+/* 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], 0, NULL);
+}
+
+/* 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], 0, NULL);
+}
+
+/* ServiceCounterDataType */
+static UA_INLINE UA_StatusCode
+UA_ServiceCounterDataType_encodeBinary(const UA_ServiceCounterDataType *src, UA_Byte **bufPos, const UA_Byte **bufEnd) {
+ return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_SERVICECOUNTERDATATYPE], bufPos, bufEnd, NULL, NULL);
+}
+static UA_INLINE UA_StatusCode
+UA_ServiceCounterDataType_decodeBinary(const UA_ByteString *src, size_t *offset, UA_ServiceCounterDataType *dst) {
+ return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_SERVICECOUNTERDATATYPE], 0, NULL);
+}
+
+/* ModelChangeStructureDataType */
+static UA_INLINE UA_StatusCode
+UA_ModelChangeStructureDataType_encodeBinary(const UA_ModelChangeStructureDataType *src, UA_Byte **bufPos, const UA_Byte **bufEnd) {
+ return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_MODELCHANGESTRUCTUREDATATYPE], bufPos, bufEnd, NULL, NULL);
+}
+static UA_INLINE UA_StatusCode
+UA_ModelChangeStructureDataType_decodeBinary(const UA_ByteString *src, size_t *offset, UA_ModelChangeStructureDataType *dst) {
+ return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_MODELCHANGESTRUCTUREDATATYPE], 0, NULL);
+}
+
+/* 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], 0, NULL);
+}
+
+/* IdType */
+static UA_INLINE UA_StatusCode
+UA_IdType_encodeBinary(const UA_IdType *src, UA_Byte **bufPos, const UA_Byte **bufEnd) {
+ return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_IDTYPE], bufPos, bufEnd, NULL, NULL);
+}
+static UA_INLINE UA_StatusCode
+UA_IdType_decodeBinary(const UA_ByteString *src, size_t *offset, UA_IdType *dst) {
+ return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_IDTYPE], 0, NULL);
+}
+
+/* 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], 0, NULL);
+}
+
+/* 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], 0, NULL);
+}
+
+/* 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], 0, NULL);
+}
+
+/* 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], 0, NULL);
+}
+
+/* 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], 0, NULL);
+}
+
+/* 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], 0, NULL);
+}
+
+/* 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], 0, NULL);
+}
+
+/* QueryNextResponse */
+static UA_INLINE UA_StatusCode
+UA_QueryNextResponse_encodeBinary(const UA_QueryNextResponse *src, UA_Byte **bufPos, const UA_Byte **bufEnd) {
+ return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_QUERYNEXTRESPONSE], bufPos, bufEnd, NULL, NULL);
+}
+static UA_INLINE UA_StatusCode
+UA_QueryNextResponse_decodeBinary(const UA_ByteString *src, size_t *offset, UA_QueryNextResponse *dst) {
+ return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_QUERYNEXTRESPONSE], 0, NULL);
+}
+
+/* DiscoveryConfiguration */
+static UA_INLINE UA_StatusCode
+UA_DiscoveryConfiguration_encodeBinary(const UA_DiscoveryConfiguration *src, UA_Byte **bufPos, const UA_Byte **bufEnd) {
+ return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_DISCOVERYCONFIGURATION], bufPos, bufEnd, NULL, NULL);
+}
+static UA_INLINE UA_StatusCode
+UA_DiscoveryConfiguration_decodeBinary(const UA_ByteString *src, size_t *offset, UA_DiscoveryConfiguration *dst) {
+ return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_DISCOVERYCONFIGURATION], 0, NULL);
+}
+
+/* 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], 0, NULL);
+}
+
+/* EndpointUrlListDataType */
+static UA_INLINE UA_StatusCode
+UA_EndpointUrlListDataType_encodeBinary(const UA_EndpointUrlListDataType *src, UA_Byte **bufPos, const UA_Byte **bufEnd) {
+ return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_ENDPOINTURLLISTDATATYPE], bufPos, bufEnd, NULL, NULL);
+}
+static UA_INLINE UA_StatusCode
+UA_EndpointUrlListDataType_decodeBinary(const UA_ByteString *src, size_t *offset, UA_EndpointUrlListDataType *dst) {
+ return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_ENDPOINTURLLISTDATATYPE], 0, NULL);
+}
+
+/* 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], 0, NULL);
+}
+
+/* QueryNextRequest */
+static UA_INLINE UA_StatusCode
+UA_QueryNextRequest_encodeBinary(const UA_QueryNextRequest *src, UA_Byte **bufPos, const UA_Byte **bufEnd) {
+ return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_QUERYNEXTREQUEST], bufPos, bufEnd, NULL, NULL);
+}
+static UA_INLINE UA_StatusCode
+UA_QueryNextRequest_decodeBinary(const UA_ByteString *src, size_t *offset, UA_QueryNextRequest *dst) {
+ return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_QUERYNEXTREQUEST], 0, NULL);
+}
+
+/* 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], 0, NULL);
+}
+
+/* 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], 0, NULL);
+}
+
+/* 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], 0, NULL);
+}
+
+/* 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], 0, NULL);
+}
+
+/* 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], 0, NULL);
+}
+
+/* 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], 0, NULL);
+}
+
+/* RedundantServerDataType */
+static UA_INLINE UA_StatusCode
+UA_RedundantServerDataType_encodeBinary(const UA_RedundantServerDataType *src, UA_Byte **bufPos, const UA_Byte **bufEnd) {
+ return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_REDUNDANTSERVERDATATYPE], bufPos, bufEnd, NULL, NULL);
+}
+static UA_INLINE UA_StatusCode
+UA_RedundantServerDataType_decodeBinary(const UA_ByteString *src, size_t *offset, UA_RedundantServerDataType *dst) {
+ return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_REDUNDANTSERVERDATATYPE], 0, NULL);
+}
+
+/* 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], 0, NULL);
+}
+
+/* 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], 0, NULL);
+}
+
+/* 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], 0, NULL);
+}
+
+/* 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], 0, NULL);
+}
+
+/* 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], 0, NULL);
+}
+
+/* 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], 0, NULL);
+}
+
+/* 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], 0, NULL);
+}
+
+/* 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], 0, NULL);
+}
+
+/* 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], 0, NULL);
+}
+
+/* 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], 0, NULL);
+}
+
+/* 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], 0, NULL);
+}
+
+/* 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], 0, NULL);
+}
+
+/* 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], 0, NULL);
+}
+
+/* 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], 0, NULL);
+}
+
+/* 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], 0, NULL);
+}
+
+/* SessionSecurityDiagnosticsDataType */
+static UA_INLINE UA_StatusCode
+UA_SessionSecurityDiagnosticsDataType_encodeBinary(const UA_SessionSecurityDiagnosticsDataType *src, UA_Byte **bufPos, const UA_Byte **bufEnd) {
+ return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_SESSIONSECURITYDIAGNOSTICSDATATYPE], bufPos, bufEnd, NULL, NULL);
+}
+static UA_INLINE UA_StatusCode
+UA_SessionSecurityDiagnosticsDataType_decodeBinary(const UA_ByteString *src, size_t *offset, UA_SessionSecurityDiagnosticsDataType *dst) {
+ return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_SESSIONSECURITYDIAGNOSTICSDATATYPE], 0, NULL);
+}
+
+/* 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], 0, NULL);
+}
+
+/* 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], 0, NULL);
+}
+
+/* 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], 0, NULL);
+}
+
+/* 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], 0, NULL);
+}
+
+/* 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], 0, NULL);
+}
+
+/* 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], 0, NULL);
+}
+
+/* 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], 0, NULL);
+}
+
+/* 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], 0, NULL);
+}
+
+/* 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], 0, NULL);
+}
+
+/* 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], 0, NULL);
+}
+
+/* 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], 0, NULL);
+}
+
+/* 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], 0, NULL);
+}
+
+/* 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], 0, NULL);
+}
+
+/* RegisterServerResponse */
+static UA_INLINE UA_StatusCode
+UA_RegisterServerResponse_encodeBinary(const UA_RegisterServerResponse *src, UA_Byte **bufPos, const UA_Byte **bufEnd) {
+ return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_REGISTERSERVERRESPONSE], bufPos, bufEnd, NULL, NULL);
+}
+static UA_INLINE UA_StatusCode
+UA_RegisterServerResponse_decodeBinary(const UA_ByteString *src, size_t *offset, UA_RegisterServerResponse *dst) {
+ return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_REGISTERSERVERRESPONSE], 0, NULL);
+}
+
+/* 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], 0, NULL);
+}
+
+/* QueryDataDescription */
+static UA_INLINE UA_StatusCode
+UA_QueryDataDescription_encodeBinary(const UA_QueryDataDescription *src, UA_Byte **bufPos, const UA_Byte **bufEnd) {
+ return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_QUERYDATADESCRIPTION], bufPos, bufEnd, NULL, NULL);
+}
+static UA_INLINE UA_StatusCode
+UA_QueryDataDescription_decodeBinary(const UA_ByteString *src, size_t *offset, UA_QueryDataDescription *dst) {
+ return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_QUERYDATADESCRIPTION], 0, NULL);
+}
+
+/* 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], 0, NULL);
+}
+
+/* NetworkGroupDataType */
+static UA_INLINE UA_StatusCode
+UA_NetworkGroupDataType_encodeBinary(const UA_NetworkGroupDataType *src, UA_Byte **bufPos, const UA_Byte **bufEnd) {
+ return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_NETWORKGROUPDATATYPE], bufPos, bufEnd, NULL, NULL);
+}
+static UA_INLINE UA_StatusCode
+UA_NetworkGroupDataType_decodeBinary(const UA_ByteString *src, size_t *offset, UA_NetworkGroupDataType *dst) {
+ return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_NETWORKGROUPDATATYPE], 0, NULL);
+}
+
+/* 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], 0, NULL);
+}
+
+/* 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], 0, NULL);
+}
+
+/* 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], 0, NULL);
+}
+
+/* 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], 0, NULL);
+}
+
+/* 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], 0, NULL);
+}
+
+/* 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], 0, NULL);
+}
+
+/* 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], 0, NULL);
+}
+
+/* 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], 0, NULL);
+}
+
+/* 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], 0, NULL);
+}
+
+/* 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], 0, NULL);
+}
+
+/* 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], 0, NULL);
+}
+
+/* RegisterServer2Response */
+static UA_INLINE UA_StatusCode
+UA_RegisterServer2Response_encodeBinary(const UA_RegisterServer2Response *src, UA_Byte **bufPos, const UA_Byte **bufEnd) {
+ return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_REGISTERSERVER2RESPONSE], bufPos, bufEnd, NULL, NULL);
+}
+static UA_INLINE UA_StatusCode
+UA_RegisterServer2Response_decodeBinary(const UA_ByteString *src, size_t *offset, UA_RegisterServer2Response *dst) {
+ return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_REGISTERSERVER2RESPONSE], 0, NULL);
+}
+
+/* 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], 0, NULL);
+}
+
+/* NodeTypeDescription */
+static UA_INLINE UA_StatusCode
+UA_NodeTypeDescription_encodeBinary(const UA_NodeTypeDescription *src, UA_Byte **bufPos, const UA_Byte **bufEnd) {
+ return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_NODETYPEDESCRIPTION], bufPos, bufEnd, NULL, NULL);
+}
+static UA_INLINE UA_StatusCode
+UA_NodeTypeDescription_decodeBinary(const UA_ByteString *src, size_t *offset, UA_NodeTypeDescription *dst) {
+ return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_NODETYPEDESCRIPTION], 0, NULL);
+}
+
+/* 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], 0, NULL);
+}
+
+/* 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], 0, NULL);
+}
+
+/* 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], 0, NULL);
+}
+
+/* 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], 0, NULL);
+}
+
+/* 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], 0, NULL);
+}
+
+/* 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], 0, NULL);
+}
+
+/* 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], 0, NULL);
+}
+
+/* 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], 0, NULL);
+}
+
+/* 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], 0, NULL);
+}
+
+/* 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], 0, NULL);
+}
+
+/* SessionDiagnosticsDataType */
+static UA_INLINE UA_StatusCode
+UA_SessionDiagnosticsDataType_encodeBinary(const UA_SessionDiagnosticsDataType *src, UA_Byte **bufPos, const UA_Byte **bufEnd) {
+ return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_SESSIONDIAGNOSTICSDATATYPE], bufPos, bufEnd, NULL, NULL);
+}
+static UA_INLINE UA_StatusCode
+UA_SessionDiagnosticsDataType_decodeBinary(const UA_ByteString *src, size_t *offset, UA_SessionDiagnosticsDataType *dst) {
+ return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_SESSIONDIAGNOSTICSDATATYPE], 0, NULL);
+}
+
+/* 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], 0, NULL);
+}
+
+/* RegisteredServer */
+static UA_INLINE UA_StatusCode
+UA_RegisteredServer_encodeBinary(const UA_RegisteredServer *src, UA_Byte **bufPos, const UA_Byte **bufEnd) {
+ return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_REGISTEREDSERVER], bufPos, bufEnd, NULL, NULL);
+}
+static UA_INLINE UA_StatusCode
+UA_RegisteredServer_decodeBinary(const UA_ByteString *src, size_t *offset, UA_RegisteredServer *dst) {
+ return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_REGISTEREDSERVER], 0, NULL);
+}
+
+/* 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], 0, NULL);
+}
+
+/* RegisterServerRequest */
+static UA_INLINE UA_StatusCode
+UA_RegisterServerRequest_encodeBinary(const UA_RegisterServerRequest *src, UA_Byte **bufPos, const UA_Byte **bufEnd) {
+ return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_REGISTERSERVERREQUEST], bufPos, bufEnd, NULL, NULL);
+}
+static UA_INLINE UA_StatusCode
+UA_RegisterServerRequest_decodeBinary(const UA_ByteString *src, size_t *offset, UA_RegisterServerRequest *dst) {
+ return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_REGISTERSERVERREQUEST], 0, NULL);
+}
+
+/* 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], 0, NULL);
+}
+
+/* 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], 0, NULL);
+}
+
+/* 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], 0, NULL);
+}
+
+/* QueryFirstResponse */
+static UA_INLINE UA_StatusCode
+UA_QueryFirstResponse_encodeBinary(const UA_QueryFirstResponse *src, UA_Byte **bufPos, const UA_Byte **bufEnd) {
+ return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_QUERYFIRSTRESPONSE], bufPos, bufEnd, NULL, NULL);
+}
+static UA_INLINE UA_StatusCode
+UA_QueryFirstResponse_decodeBinary(const UA_ByteString *src, size_t *offset, UA_QueryFirstResponse *dst) {
+ return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_QUERYFIRSTRESPONSE], 0, NULL);
+}
+
+/* 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], 0, NULL);
+}
+
+/* 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], 0, NULL);
+}
+
+/* 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], 0, NULL);
+}
+
+/* RegisterServer2Request */
+static UA_INLINE UA_StatusCode
+UA_RegisterServer2Request_encodeBinary(const UA_RegisterServer2Request *src, UA_Byte **bufPos, const UA_Byte **bufEnd) {
+ return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_REGISTERSERVER2REQUEST], bufPos, bufEnd, NULL, NULL);
+}
+static UA_INLINE UA_StatusCode
+UA_RegisterServer2Request_decodeBinary(const UA_ByteString *src, size_t *offset, UA_RegisterServer2Request *dst) {
+ return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_REGISTERSERVER2REQUEST], 0, NULL);
+}
+
+/* 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], 0, NULL);
+}
+
+/* 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], 0, NULL);
+}
+
+/* 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], 0, NULL);
+}
+
+/* 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], 0, NULL);
+}
+
+/* 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], 0, NULL);
+}
+
+/* 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], 0, NULL);
+}
+
+/* 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], 0, NULL);
+}
+
+/* QueryFirstRequest */
+static UA_INLINE UA_StatusCode
+UA_QueryFirstRequest_encodeBinary(const UA_QueryFirstRequest *src, UA_Byte **bufPos, const UA_Byte **bufEnd) {
+ return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_QUERYFIRSTREQUEST], bufPos, bufEnd, NULL, NULL);
+}
+static UA_INLINE UA_StatusCode
+UA_QueryFirstRequest_decodeBinary(const UA_ByteString *src, size_t *offset, UA_QueryFirstRequest *dst) {
+ return UA_decodeBinary(src, offset, dst, &UA_TYPES[UA_TYPES_QUERYFIRSTREQUEST], 0, NULL);
+}
+
+/*********************************** amalgamated original file "/home/jvoe/open62541/build/src_generated/ua_transport_generated.h" ***********************************/
+
+/* Generated from Opc.Ua.Types.bsd, Custom.Opc.Ua.Transport.bsd with script /home/jvoe/open62541/tools/generate_datatypes.py
+ * on host rigel by user jvoe at 2019-01-04 01:18:40 */
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef UA_NO_AMALGAMATION
+
+#else
+#endif
+
+
+/**
+ * Every type is assigned an index in an array containing the type descriptions.
+ * These descriptions are used during type handling (copying, deletion,
+ * binary encoding, ...). */
+#define UA_TRANSPORT_COUNT 12
+extern UA_EXPORT const UA_DataType UA_TRANSPORT[UA_TRANSPORT_COUNT];
+
+/**
+ * SecureConversationMessageAbortBody
+ * ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ * Secure Conversation Message Abort Body */
+typedef struct {
+ UA_UInt32 error;
+ UA_String reason;
+} UA_SecureConversationMessageAbortBody;
+
+#define UA_TRANSPORT_SECURECONVERSATIONMESSAGEABORTBODY 0
+
+/**
+ * SecureConversationMessageFooter
+ * ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ * Secure Conversation Message Footer */
+typedef struct {
+ size_t paddingSize;
+ UA_Byte *padding;
+ UA_Byte signature;
+} UA_SecureConversationMessageFooter;
+
+#define UA_TRANSPORT_SECURECONVERSATIONMESSAGEFOOTER 1
+
+/**
+ * TcpHelloMessage
+ * ^^^^^^^^^^^^^^^
+ * Hello Message */
+typedef struct {
+ UA_UInt32 protocolVersion;
+ UA_UInt32 receiveBufferSize;
+ UA_UInt32 sendBufferSize;
+ UA_UInt32 maxMessageSize;
+ UA_UInt32 maxChunkCount;
+ UA_String endpointUrl;
+} UA_TcpHelloMessage;
+
+#define UA_TRANSPORT_TCPHELLOMESSAGE 2
+
+/**
+ * TcpErrorMessage
+ * ^^^^^^^^^^^^^^^
+ * Error Message */
+typedef struct {
+ UA_UInt32 error;
+ UA_String reason;
+} UA_TcpErrorMessage;
+
+#define UA_TRANSPORT_TCPERRORMESSAGE 3
+
+/**
+ * MessageType
+ * ^^^^^^^^^^^
+ * Message Type and whether the message contains an intermediate chunk */
+typedef enum {
+ UA_MESSAGETYPE_ACK = 0x4B4341,
+ UA_MESSAGETYPE_HEL = 0x4C4548,
+ UA_MESSAGETYPE_MSG = 0x47534D,
+ UA_MESSAGETYPE_OPN = 0x4E504F,
+ UA_MESSAGETYPE_CLO = 0x4F4C43,
+ UA_MESSAGETYPE_ERR = 0x525245,
+ __UA_MESSAGETYPE_FORCE32BIT = 0x7fffffff
+} UA_MessageType;
+UA_STATIC_ASSERT(sizeof(UA_MessageType) == sizeof(UA_Int32), enum_must_be_32bit);
+
+#define UA_TRANSPORT_MESSAGETYPE 4
+
+/**
+ * AsymmetricAlgorithmSecurityHeader
+ * ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ * Security Header */
+typedef struct {
+ UA_ByteString securityPolicyUri;
+ UA_ByteString senderCertificate;
+ UA_ByteString receiverCertificateThumbprint;
+} UA_AsymmetricAlgorithmSecurityHeader;
+
+#define UA_TRANSPORT_ASYMMETRICALGORITHMSECURITYHEADER 5
+
+/**
+ * TcpAcknowledgeMessage
+ * ^^^^^^^^^^^^^^^^^^^^^
+ * Acknowledge Message */
+typedef struct {
+ UA_UInt32 protocolVersion;
+ UA_UInt32 receiveBufferSize;
+ UA_UInt32 sendBufferSize;
+ UA_UInt32 maxMessageSize;
+ UA_UInt32 maxChunkCount;
+} UA_TcpAcknowledgeMessage;
+
+#define UA_TRANSPORT_TCPACKNOWLEDGEMESSAGE 6
+
+/**
+ * SequenceHeader
+ * ^^^^^^^^^^^^^^
+ * Secure Layer Sequence Header */
+typedef struct {
+ UA_UInt32 sequenceNumber;
+ UA_UInt32 requestId;
+} UA_SequenceHeader;
+
+#define UA_TRANSPORT_SEQUENCEHEADER 7
+
+/**
+ * TcpMessageHeader
+ * ^^^^^^^^^^^^^^^^
+ * TCP Header */
+typedef struct {
+ UA_UInt32 messageTypeAndChunkType;
+ UA_UInt32 messageSize;
+} UA_TcpMessageHeader;
+
+#define UA_TRANSPORT_TCPMESSAGEHEADER 8
+
+/**
+ * ChunkType
+ * ^^^^^^^^^
+ * Type of the chunk */
+typedef enum {
+ UA_CHUNKTYPE_FINAL = 0x46000000,
+ UA_CHUNKTYPE_INTERMEDIATE = 0x43000000,
+ UA_CHUNKTYPE_ABORT = 0x41000000,
+ __UA_CHUNKTYPE_FORCE32BIT = 0x7fffffff
+} UA_ChunkType;
+UA_STATIC_ASSERT(sizeof(UA_ChunkType) == sizeof(UA_Int32), enum_must_be_32bit);
+
+#define UA_TRANSPORT_CHUNKTYPE 9
+
+/**
+ * SymmetricAlgorithmSecurityHeader
+ * ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ * Secure Layer Symmetric Algorithm Header */
+typedef struct {
+ UA_UInt32 tokenId;
+} UA_SymmetricAlgorithmSecurityHeader;
+
+#define UA_TRANSPORT_SYMMETRICALGORITHMSECURITYHEADER 10
+
+/**
+ * SecureConversationMessageHeader
+ * ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ * Secure Layer Sequence Header */
+typedef struct {
+ UA_TcpMessageHeader messageHeader;
+ UA_UInt32 secureChannelId;
+} UA_SecureConversationMessageHeader;
+
+#define UA_TRANSPORT_SECURECONVERSATIONMESSAGEHEADER 11
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+
+/*********************************** amalgamated original file "/home/jvoe/open62541/build/src_generated/ua_transport_generated_handling.h" ***********************************/
+
+/* Generated from Opc.Ua.Types.bsd, Custom.Opc.Ua.Transport.bsd with script /home/jvoe/open62541/tools/generate_datatypes.py
+ * on host rigel by user jvoe at 2019-01-04 01:18:40 */
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+#if defined(__GNUC__) && __GNUC__ >= 4 && __GNUC_MINOR__ >= 6
+# pragma GCC diagnostic push
+# pragma GCC diagnostic ignored "-Wmissing-field-initializers"
+# pragma GCC diagnostic ignored "-Wmissing-braces"
+#endif
+
+
+/* SecureConversationMessageAbortBody */
+static UA_INLINE void
+UA_SecureConversationMessageAbortBody_init(UA_SecureConversationMessageAbortBody *p) {
+ memset(p, 0, sizeof(UA_SecureConversationMessageAbortBody));
+}
+
+static UA_INLINE UA_SecureConversationMessageAbortBody *
+UA_SecureConversationMessageAbortBody_new(void) {
+ return (UA_SecureConversationMessageAbortBody*)UA_new(&UA_TRANSPORT[UA_TRANSPORT_SECURECONVERSATIONMESSAGEABORTBODY]);
+}
+
+static UA_INLINE UA_StatusCode
+UA_SecureConversationMessageAbortBody_copy(const UA_SecureConversationMessageAbortBody *src, UA_SecureConversationMessageAbortBody *dst) {
+ return UA_copy(src, dst, &UA_TRANSPORT[UA_TRANSPORT_SECURECONVERSATIONMESSAGEABORTBODY]);
+}
+
+static UA_INLINE void
+UA_SecureConversationMessageAbortBody_deleteMembers(UA_SecureConversationMessageAbortBody *p) {
+ UA_deleteMembers(p, &UA_TRANSPORT[UA_TRANSPORT_SECURECONVERSATIONMESSAGEABORTBODY]);
+}
+
+static UA_INLINE void
+UA_SecureConversationMessageAbortBody_delete(UA_SecureConversationMessageAbortBody *p) {
+ UA_delete(p, &UA_TRANSPORT[UA_TRANSPORT_SECURECONVERSATIONMESSAGEABORTBODY]);
+}
+
+/* SecureConversationMessageFooter */
+static UA_INLINE void
+UA_SecureConversationMessageFooter_init(UA_SecureConversationMessageFooter *p) {
+ memset(p, 0, sizeof(UA_SecureConversationMessageFooter));
+}
+
+static UA_INLINE UA_SecureConversationMessageFooter *
+UA_SecureConversationMessageFooter_new(void) {
+ return (UA_SecureConversationMessageFooter*)UA_new(&UA_TRANSPORT[UA_TRANSPORT_SECURECONVERSATIONMESSAGEFOOTER]);
+}
+
+static UA_INLINE UA_StatusCode
+UA_SecureConversationMessageFooter_copy(const UA_SecureConversationMessageFooter *src, UA_SecureConversationMessageFooter *dst) {
+ return UA_copy(src, dst, &UA_TRANSPORT[UA_TRANSPORT_SECURECONVERSATIONMESSAGEFOOTER]);
+}
+
+static UA_INLINE void
+UA_SecureConversationMessageFooter_deleteMembers(UA_SecureConversationMessageFooter *p) {
+ UA_deleteMembers(p, &UA_TRANSPORT[UA_TRANSPORT_SECURECONVERSATIONMESSAGEFOOTER]);
+}
+
+static UA_INLINE void
+UA_SecureConversationMessageFooter_delete(UA_SecureConversationMessageFooter *p) {
+ UA_delete(p, &UA_TRANSPORT[UA_TRANSPORT_SECURECONVERSATIONMESSAGEFOOTER]);
+}
+
+/* TcpHelloMessage */
+static UA_INLINE void
+UA_TcpHelloMessage_init(UA_TcpHelloMessage *p) {
+ memset(p, 0, sizeof(UA_TcpHelloMessage));
+}
+
+static UA_INLINE UA_TcpHelloMessage *
+UA_TcpHelloMessage_new(void) {
+ return (UA_TcpHelloMessage*)UA_new(&UA_TRANSPORT[UA_TRANSPORT_TCPHELLOMESSAGE]);
+}
+
+static UA_INLINE UA_StatusCode
+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_TcpHelloMessage_deleteMembers(UA_TcpHelloMessage *p) {
+ UA_deleteMembers(p, &UA_TRANSPORT[UA_TRANSPORT_TCPHELLOMESSAGE]);
+}
+
+static UA_INLINE void
+UA_TcpHelloMessage_delete(UA_TcpHelloMessage *p) {
+ UA_delete(p, &UA_TRANSPORT[UA_TRANSPORT_TCPHELLOMESSAGE]);
+}
+
+/* TcpErrorMessage */
+static UA_INLINE void
+UA_TcpErrorMessage_init(UA_TcpErrorMessage *p) {
+ memset(p, 0, sizeof(UA_TcpErrorMessage));
+}
+
+static UA_INLINE UA_TcpErrorMessage *
+UA_TcpErrorMessage_new(void) {
+ return (UA_TcpErrorMessage*)UA_new(&UA_TRANSPORT[UA_TRANSPORT_TCPERRORMESSAGE]);
+}
+
+static UA_INLINE UA_StatusCode
+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_TcpErrorMessage_deleteMembers(UA_TcpErrorMessage *p) {
+ UA_deleteMembers(p, &UA_TRANSPORT[UA_TRANSPORT_TCPERRORMESSAGE]);
+}
+
+static UA_INLINE void
+UA_TcpErrorMessage_delete(UA_TcpErrorMessage *p) {
+ UA_delete(p, &UA_TRANSPORT[UA_TRANSPORT_TCPERRORMESSAGE]);
+}
+
+/* MessageType */
+static UA_INLINE void
+UA_MessageType_init(UA_MessageType *p) {
+ memset(p, 0, sizeof(UA_MessageType));
+}
+
+static UA_INLINE UA_MessageType *
+UA_MessageType_new(void) {
+ return (UA_MessageType*)UA_new(&UA_TRANSPORT[UA_TRANSPORT_MESSAGETYPE]);
+}
+
+static UA_INLINE UA_StatusCode
+UA_MessageType_copy(const UA_MessageType *src, UA_MessageType *dst) {
+ *dst = *src;
+ return UA_STATUSCODE_GOOD;
+}
+
+static UA_INLINE void
+UA_MessageType_deleteMembers(UA_MessageType *p) { }
+
+static UA_INLINE void
+UA_MessageType_delete(UA_MessageType *p) {
+ UA_delete(p, &UA_TRANSPORT[UA_TRANSPORT_MESSAGETYPE]);
+}
+
+/* AsymmetricAlgorithmSecurityHeader */
+static UA_INLINE void
+UA_AsymmetricAlgorithmSecurityHeader_init(UA_AsymmetricAlgorithmSecurityHeader *p) {
+ memset(p, 0, sizeof(UA_AsymmetricAlgorithmSecurityHeader));
+}
+
+static UA_INLINE UA_AsymmetricAlgorithmSecurityHeader *
+UA_AsymmetricAlgorithmSecurityHeader_new(void) {
+ return (UA_AsymmetricAlgorithmSecurityHeader*)UA_new(&UA_TRANSPORT[UA_TRANSPORT_ASYMMETRICALGORITHMSECURITYHEADER]);
+}
+
+static UA_INLINE UA_StatusCode
+UA_AsymmetricAlgorithmSecurityHeader_copy(const UA_AsymmetricAlgorithmSecurityHeader *src, UA_AsymmetricAlgorithmSecurityHeader *dst) {
+ return UA_copy(src, dst, &UA_TRANSPORT[UA_TRANSPORT_ASYMMETRICALGORITHMSECURITYHEADER]);
+}
+
+static UA_INLINE void
+UA_AsymmetricAlgorithmSecurityHeader_deleteMembers(UA_AsymmetricAlgorithmSecurityHeader *p) {
+ UA_deleteMembers(p, &UA_TRANSPORT[UA_TRANSPORT_ASYMMETRICALGORITHMSECURITYHEADER]);
+}
+
+static UA_INLINE void
+UA_AsymmetricAlgorithmSecurityHeader_delete(UA_AsymmetricAlgorithmSecurityHeader *p) {
+ UA_delete(p, &UA_TRANSPORT[UA_TRANSPORT_ASYMMETRICALGORITHMSECURITYHEADER]);
+}
+
+/* TcpAcknowledgeMessage */
+static UA_INLINE void
+UA_TcpAcknowledgeMessage_init(UA_TcpAcknowledgeMessage *p) {
+ memset(p, 0, sizeof(UA_TcpAcknowledgeMessage));
+}
+
+static UA_INLINE UA_TcpAcknowledgeMessage *
+UA_TcpAcknowledgeMessage_new(void) {
+ return (UA_TcpAcknowledgeMessage*)UA_new(&UA_TRANSPORT[UA_TRANSPORT_TCPACKNOWLEDGEMESSAGE]);
+}
+
+static UA_INLINE UA_StatusCode
+UA_TcpAcknowledgeMessage_copy(const UA_TcpAcknowledgeMessage *src, UA_TcpAcknowledgeMessage *dst) {
+ *dst = *src;
+ return UA_STATUSCODE_GOOD;
+}
+
+static UA_INLINE void
+UA_TcpAcknowledgeMessage_deleteMembers(UA_TcpAcknowledgeMessage *p) { }
+
+static UA_INLINE void
+UA_TcpAcknowledgeMessage_delete(UA_TcpAcknowledgeMessage *p) {
+ UA_delete(p, &UA_TRANSPORT[UA_TRANSPORT_TCPACKNOWLEDGEMESSAGE]);
+}
+
+/* SequenceHeader */
+static UA_INLINE void
+UA_SequenceHeader_init(UA_SequenceHeader *p) {
+ memset(p, 0, sizeof(UA_SequenceHeader));
+}
+
+static UA_INLINE UA_SequenceHeader *
+UA_SequenceHeader_new(void) {
+ return (UA_SequenceHeader*)UA_new(&UA_TRANSPORT[UA_TRANSPORT_SEQUENCEHEADER]);
+}
+
+static UA_INLINE UA_StatusCode
+UA_SequenceHeader_copy(const UA_SequenceHeader *src, UA_SequenceHeader *dst) {
+ *dst = *src;
+ return UA_STATUSCODE_GOOD;
+}
+
+static UA_INLINE void
+UA_SequenceHeader_deleteMembers(UA_SequenceHeader *p) { }
+
+static UA_INLINE void
+UA_SequenceHeader_delete(UA_SequenceHeader *p) {
+ UA_delete(p, &UA_TRANSPORT[UA_TRANSPORT_SEQUENCEHEADER]);
+}
+
+/* TcpMessageHeader */
+static UA_INLINE void
+UA_TcpMessageHeader_init(UA_TcpMessageHeader *p) {
+ memset(p, 0, sizeof(UA_TcpMessageHeader));
+}
+
+static UA_INLINE UA_TcpMessageHeader *
+UA_TcpMessageHeader_new(void) {
+ return (UA_TcpMessageHeader*)UA_new(&UA_TRANSPORT[UA_TRANSPORT_TCPMESSAGEHEADER]);
+}
+
+static UA_INLINE UA_StatusCode
+UA_TcpMessageHeader_copy(const UA_TcpMessageHeader *src, UA_TcpMessageHeader *dst) {
+ *dst = *src;
+ return UA_STATUSCODE_GOOD;
+}
+
+static UA_INLINE void
+UA_TcpMessageHeader_deleteMembers(UA_TcpMessageHeader *p) { }
+
+static UA_INLINE void
+UA_TcpMessageHeader_delete(UA_TcpMessageHeader *p) {
+ UA_delete(p, &UA_TRANSPORT[UA_TRANSPORT_TCPMESSAGEHEADER]);
+}
+
+/* ChunkType */
+static UA_INLINE void
+UA_ChunkType_init(UA_ChunkType *p) {
+ memset(p, 0, sizeof(UA_ChunkType));
+}
+
+static UA_INLINE UA_ChunkType *
+UA_ChunkType_new(void) {
+ return (UA_ChunkType*)UA_new(&UA_TRANSPORT[UA_TRANSPORT_CHUNKTYPE]);
+}
+
+static UA_INLINE UA_StatusCode
+UA_ChunkType_copy(const UA_ChunkType *src, UA_ChunkType *dst) {
+ *dst = *src;
+ return UA_STATUSCODE_GOOD;
+}
+
+static UA_INLINE void
+UA_ChunkType_deleteMembers(UA_ChunkType *p) { }
+
+static UA_INLINE void
+UA_ChunkType_delete(UA_ChunkType *p) {
+ UA_delete(p, &UA_TRANSPORT[UA_TRANSPORT_CHUNKTYPE]);
+}
+
+/* SymmetricAlgorithmSecurityHeader */
+static UA_INLINE void
+UA_SymmetricAlgorithmSecurityHeader_init(UA_SymmetricAlgorithmSecurityHeader *p) {
+ memset(p, 0, sizeof(UA_SymmetricAlgorithmSecurityHeader));
+}
+
+static UA_INLINE UA_SymmetricAlgorithmSecurityHeader *
+UA_SymmetricAlgorithmSecurityHeader_new(void) {
+ return (UA_SymmetricAlgorithmSecurityHeader*)UA_new(&UA_TRANSPORT[UA_TRANSPORT_SYMMETRICALGORITHMSECURITYHEADER]);
+}
+
+static UA_INLINE UA_StatusCode
+UA_SymmetricAlgorithmSecurityHeader_copy(const UA_SymmetricAlgorithmSecurityHeader *src, UA_SymmetricAlgorithmSecurityHeader *dst) {
+ *dst = *src;
+ return UA_STATUSCODE_GOOD;
+}
+
+static UA_INLINE void
+UA_SymmetricAlgorithmSecurityHeader_deleteMembers(UA_SymmetricAlgorithmSecurityHeader *p) { }
+
+static UA_INLINE void
+UA_SymmetricAlgorithmSecurityHeader_delete(UA_SymmetricAlgorithmSecurityHeader *p) {
+ UA_delete(p, &UA_TRANSPORT[UA_TRANSPORT_SYMMETRICALGORITHMSECURITYHEADER]);
+}
+
+/* SecureConversationMessageHeader */
+static UA_INLINE void
+UA_SecureConversationMessageHeader_init(UA_SecureConversationMessageHeader *p) {
+ memset(p, 0, sizeof(UA_SecureConversationMessageHeader));
+}
+
+static UA_INLINE UA_SecureConversationMessageHeader *
+UA_SecureConversationMessageHeader_new(void) {
+ return (UA_SecureConversationMessageHeader*)UA_new(&UA_TRANSPORT[UA_TRANSPORT_SECURECONVERSATIONMESSAGEHEADER]);
+}
+
+static UA_INLINE UA_StatusCode
+UA_SecureConversationMessageHeader_copy(const UA_SecureConversationMessageHeader *src, UA_SecureConversationMessageHeader *dst) {
+ *dst = *src;
+ return UA_STATUSCODE_GOOD;
+}
+
+static UA_INLINE void
+UA_SecureConversationMessageHeader_deleteMembers(UA_SecureConversationMessageHeader *p) { }
+
+static UA_INLINE void
+UA_SecureConversationMessageHeader_delete(UA_SecureConversationMessageHeader *p) {
+ UA_delete(p, &UA_TRANSPORT[UA_TRANSPORT_SECURECONVERSATIONMESSAGEHEADER]);
+}
+
+#if defined(__GNUC__) && __GNUC__ >= 4 && __GNUC_MINOR__ >= 6
+# pragma GCC diagnostic pop
+#endif
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+
+/*********************************** amalgamated original file "/home/jvoe/open62541/build/src_generated/ua_transport_generated_encoding_binary.h" ***********************************/
+
+/* Generated from Opc.Ua.Types.bsd, Custom.Opc.Ua.Transport.bsd with script /home/jvoe/open62541/tools/generate_datatypes.py
+ * on host rigel by user jvoe at 2019-01-04 01:18:40 */
+
+
+/* SecureConversationMessageAbortBody */
+static UA_INLINE UA_StatusCode
+UA_SecureConversationMessageAbortBody_encodeBinary(const UA_SecureConversationMessageAbortBody *src, UA_Byte **bufPos, const UA_Byte **bufEnd) {
+ return UA_encodeBinary(src, &UA_TRANSPORT[UA_TRANSPORT_SECURECONVERSATIONMESSAGEABORTBODY], bufPos, bufEnd, NULL, NULL);
+}
+static UA_INLINE UA_StatusCode
+UA_SecureConversationMessageAbortBody_decodeBinary(const UA_ByteString *src, size_t *offset, UA_SecureConversationMessageAbortBody *dst) {
+ return UA_decodeBinary(src, offset, dst, &UA_TRANSPORT[UA_TRANSPORT_SECURECONVERSATIONMESSAGEABORTBODY], 0, NULL);
+}
+
+/* SecureConversationMessageFooter */
+static UA_INLINE UA_StatusCode
+UA_SecureConversationMessageFooter_encodeBinary(const UA_SecureConversationMessageFooter *src, UA_Byte **bufPos, const UA_Byte **bufEnd) {
+ return UA_encodeBinary(src, &UA_TRANSPORT[UA_TRANSPORT_SECURECONVERSATIONMESSAGEFOOTER], bufPos, bufEnd, NULL, NULL);
+}
+static UA_INLINE UA_StatusCode
+UA_SecureConversationMessageFooter_decodeBinary(const UA_ByteString *src, size_t *offset, UA_SecureConversationMessageFooter *dst) {
+ return UA_decodeBinary(src, offset, dst, &UA_TRANSPORT[UA_TRANSPORT_SECURECONVERSATIONMESSAGEFOOTER], 0, NULL);
+}
+
+/* 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], 0, NULL);
+}
+
+/* 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], 0, NULL);
+}
+
+/* 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], 0, NULL);
+}
+
+/* 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], 0, NULL);
+}
+
+/* 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], 0, NULL);
+}
+
+/* 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], 0, NULL);
+}
+
+/* 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], 0, NULL);
+}
+
+/* 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], 0, NULL);
+}
+
+/* SymmetricAlgorithmSecurityHeader */
+static UA_INLINE UA_StatusCode
+UA_SymmetricAlgorithmSecurityHeader_encodeBinary(const UA_SymmetricAlgorithmSecurityHeader *src, UA_Byte **bufPos, const UA_Byte **bufEnd) {
+ return UA_encodeBinary(src, &UA_TRANSPORT[UA_TRANSPORT_SYMMETRICALGORITHMSECURITYHEADER], bufPos, bufEnd, NULL, NULL);
+}
+static UA_INLINE UA_StatusCode
+UA_SymmetricAlgorithmSecurityHeader_decodeBinary(const UA_ByteString *src, size_t *offset, UA_SymmetricAlgorithmSecurityHeader *dst) {
+ return UA_decodeBinary(src, offset, dst, &UA_TRANSPORT[UA_TRANSPORT_SYMMETRICALGORITHMSECURITYHEADER], 0, NULL);
+}
+
+/* SecureConversationMessageHeader */
+static UA_INLINE UA_StatusCode
+UA_SecureConversationMessageHeader_encodeBinary(const UA_SecureConversationMessageHeader *src, UA_Byte **bufPos, const UA_Byte **bufEnd) {
+ return UA_encodeBinary(src, &UA_TRANSPORT[UA_TRANSPORT_SECURECONVERSATIONMESSAGEHEADER], bufPos, bufEnd, NULL, NULL);
+}
+static UA_INLINE UA_StatusCode
+UA_SecureConversationMessageHeader_decodeBinary(const UA_ByteString *src, size_t *offset, UA_SecureConversationMessageHeader *dst) {
+ return UA_decodeBinary(src, offset, dst, &UA_TRANSPORT[UA_TRANSPORT_SECURECONVERSATIONMESSAGEHEADER], 0, NULL);
+}
+
+/*********************************** amalgamated original file "/home/jvoe/open62541/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
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * Copyright 2016-2017 (c) Julius Pfrommer, Fraunhofer IOSB
+ * Copyright 2016-2017 (c) Stefan Profanter, fortiss GmbH
+ * Copyright 2017 (c) Florian Palm
+ * Copyright 2017 (c) Mark Giraud, Fraunhofer IOSB
+ */
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/* The application can be the client or the server */
+typedef UA_StatusCode (*UA_Connection_processChunk)(void *application,
+ UA_Connection *connection,
+ UA_ByteString *chunk);
+
+/* The network layer may receive chopped up messages since TCP is a streaming
+ * protocol. This method calls the processChunk callback on all full chunks that
+ * were received. Dangling half-complete chunks are buffered in the connection
+ * and considered for the next received packet.
+ *
+ * If an entire chunk is received, it is forwarded directly. But the memory
+ * needs to be freed with the networklayer-specific mechanism. If a half message
+ * is received, we copy it into a local buffer. Then, the stack-specific free
+ * needs to be used.
+ *
+ * @param connection The connection
+ * @param application The client or server application
+ * @param processCallback The function pointer for processing each chunk
+ * @param packet The received packet.
+ * @return Returns UA_STATUSCODE_GOOD or an error code. When an error occurs,
+ * the ingoing message and the current buffer in the connection are
+ * freed. */
+UA_StatusCode
+UA_Connection_processChunks(UA_Connection *connection, void *application,
+ UA_Connection_processChunk processCallback,
+ const UA_ByteString *packet);
+
+/* Try to receive at least one complete chunk on the connection. This blocks the
+ * current thread up to the given timeout.
+ *
+ * @param connection The connection
+ * @param application The client or server application
+ * @param processCallback The function pointer for processing each chunk
+ * @param timeout The timeout (in milliseconds) the method will block at most.
+ * @return Returns UA_STATUSCODE_GOOD or an error code. When an timeout occurs,
+ * UA_STATUSCODE_GOODNONCRITICALTIMEOUT is returned. */
+UA_StatusCode
+UA_Connection_receiveChunksBlocking(UA_Connection *connection, void *application,
+ UA_Connection_processChunk processCallback,
+ UA_UInt32 timeout);
+
+/* When a fatal error occurs the Server shall send an Error Message to the
+ * Client and close the socket. When a Client encounters one of these errors, it
+ * shall also close the socket but does not send an Error Message. After the
+ * socket is closed a Client shall try to reconnect automatically using the
+ * mechanisms described in [...]. */
+void
+UA_Connection_sendError(UA_Connection *connection,
+ UA_TcpErrorMessage *error);
+
+void UA_Connection_detachSecureChannel(UA_Connection *connection);
+void UA_Connection_attachSecureChannel(UA_Connection *connection,
+ UA_SecureChannel *channel);
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+
+/*********************************** amalgamated original file "/home/jvoe/open62541/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
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * Copyright 2014-2018 (c) Julius Pfrommer, Fraunhofer IOSB
+ * Copyright 2017 (c) Florian Palm
+ * Copyright 2017 (c) Stefan Profanter, fortiss GmbH
+ * Copyright 2017 (c) Mark Giraud, Fraunhofer IOSB
+ */
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+#define UA_SECURE_CONVERSATION_MESSAGE_HEADER_LENGTH 12
+#define UA_SECURE_MESSAGE_HEADER_LENGTH 24
+
+/* Thread-local variables to force failure modes during testing */
+#ifdef UA_ENABLE_UNIT_TEST_FAILURE_HOOKS
+extern UA_StatusCode decrypt_verifySignatureFailure;
+extern UA_StatusCode sendAsym_sendFailure;
+extern UA_StatusCode processSym_seqNumberFailure;
+#endif
+
+/* The Session implementation differs between client and server. Still, it is
+ * expected that the Session structure begins with the SessionHeader. This is
+ * the interface that will be used by the SecureChannel. The lifecycle of
+ * Sessions is independent of the underlying SecureChannel. But every Session
+ * can be attached to only one SecureChannel. */
+typedef struct UA_SessionHeader {
+ LIST_ENTRY(UA_SessionHeader) pointers;
+ UA_NodeId authenticationToken;
+ UA_SecureChannel *channel; /* The pointer back to the SecureChannel in the session. */
+} UA_SessionHeader;
+
+/* For chunked requests */
+struct ChunkPayload {
+ SIMPLEQ_ENTRY(ChunkPayload) pointers;
+ UA_ByteString bytes;
+};
+
+struct MessageEntry {
+ LIST_ENTRY(MessageEntry) pointers;
+ UA_UInt32 requestId;
+ SIMPLEQ_HEAD(chunkpayload_pointerlist, ChunkPayload) chunkPayload;
+ size_t chunkPayloadSize;
+};
+
+typedef enum {
+ UA_SECURECHANNELSTATE_FRESH,
+ UA_SECURECHANNELSTATE_OPEN,
+ UA_SECURECHANNELSTATE_CLOSED
+} UA_SecureChannelState;
+
+struct UA_SecureChannel {
+ UA_SecureChannelState state;
+ UA_MessageSecurityMode securityMode;
+ UA_ChannelSecurityToken securityToken; /* the channelId is contained in the securityToken */
+ /* We use three tokens because when switching tokens the client is allowed to accept
+ * messages with the old token for up to 25% of the lifetime after the token would have timed out.
+ * For messages that are sent, the new token is already used, which is contained in the securityToken
+ * variable. The nextSecurityToken variable holds a newly issued token, that will be automatically
+ * revolved into the securityToken variable. This could be done with two variables, but would require
+ * greater changes to the current code. This could be done in the future after the client and networking
+ * structure has been reworked, which would make this easier to implement. */
+ UA_ChannelSecurityToken nextSecurityToken;
+ UA_ChannelSecurityToken previousSecurityToken;
+
+ /* The endpoint and context of the channel */
+ const UA_SecurityPolicy *securityPolicy;
+ void *channelContext; /* For interaction with the security policy */
+ UA_Connection *connection;
+
+ /* Asymmetric encryption info */
+ UA_ByteString remoteCertificate;
+ UA_Byte remoteCertificateThumbprint[20]; /* The thumbprint of the remote certificate */
+
+ /* Symmetric encryption info */
+ UA_ByteString remoteNonce;
+ UA_ByteString localNonce;
+
+ UA_UInt32 receiveSequenceNumber;
+ UA_UInt32 sendSequenceNumber;
+
+ LIST_HEAD(session_pointerlist, UA_SessionHeader) sessions;
+ LIST_HEAD(chunk_pointerlist, MessageEntry) chunks;
+};
+
+UA_StatusCode
+UA_SecureChannel_init(UA_SecureChannel *channel,
+ const UA_SecurityPolicy *securityPolicy,
+ const UA_ByteString *remoteCertificate);
+void UA_SecureChannel_deleteMembersCleanup(UA_SecureChannel *channel);
+
+/* Generates new keys and sets them in the channel context */
+UA_StatusCode
+UA_SecureChannel_generateNewKeys(UA_SecureChannel* channel);
+
+/* Wrapper function for generating a local nonce for the supplied channel. Uses
+ * the random generator of the channels security policy to allocate and generate
+ * a nonce with the specified length. */
+UA_StatusCode
+UA_SecureChannel_generateLocalNonce(UA_SecureChannel *channel);
+
+UA_SessionHeader *
+UA_SecureChannel_getSession(UA_SecureChannel *channel,
+ const UA_NodeId *authenticationToken);
+
+UA_StatusCode
+UA_SecureChannel_revolveTokens(UA_SecureChannel *channel);
+
+/**
+ * Sending Messages
+ * ---------------- */
+
+UA_StatusCode
+UA_SecureChannel_sendAsymmetricOPNMessage(UA_SecureChannel *channel, UA_UInt32 requestId,
+ const void *content, const UA_DataType *contentType);
+
+UA_StatusCode
+UA_SecureChannel_sendSymmetricMessage(UA_SecureChannel *channel, UA_UInt32 requestId,
+ UA_MessageType messageType, void *payload,
+ const UA_DataType *payloadType);
+
+/* The MessageContext is forwarded into the encoding layer so that we can send
+ * chunks before continuing to encode. This lets us reuse a fixed chunk-sized
+ * messages buffer. */
+typedef struct {
+ UA_SecureChannel *channel;
+ UA_UInt32 requestId;
+ UA_UInt32 messageType;
+
+ UA_UInt16 chunksSoFar;
+ size_t messageSizeSoFar;
+
+ UA_ByteString messageBuffer;
+ UA_Byte *buf_pos;
+ const UA_Byte *buf_end;
+
+ UA_Boolean final;
+} UA_MessageContext;
+
+/* Start the context of a new symmetric message. */
+UA_StatusCode
+UA_MessageContext_begin(UA_MessageContext *mc, UA_SecureChannel *channel,
+ UA_UInt32 requestId, UA_MessageType messageType);
+
+/* Encode the content and send out full chunks. If the return code is good, then
+ * the ChunkInfo contains encoded content that has not been sent. If the return
+ * code is bad, then the ChunkInfo has been cleaned up internally. */
+UA_StatusCode
+UA_MessageContext_encode(UA_MessageContext *mc, const void *content,
+ const UA_DataType *contentType);
+
+/* Sends a symmetric message already encoded in the context. The context is
+ * cleaned up, also in case of errors. */
+UA_StatusCode
+UA_MessageContext_finish(UA_MessageContext *mc);
+
+/* To be used when a failure occures when a MessageContext is open. Note that
+ * the _encode and _finish methods will clean up internally. _abort can be run
+ * on a MessageContext that has already been cleaned up before. */
+void
+UA_MessageContext_abort(UA_MessageContext *mc);
+
+/**
+ * Process Received Chunks
+ * ----------------------- */
+
+typedef UA_StatusCode
+(UA_ProcessMessageCallback)(void *application, UA_SecureChannel *channel,
+ UA_MessageType messageType, UA_UInt32 requestId,
+ const UA_ByteString *message);
+
+/* Process a single chunk. This also decrypts the chunk if required. The
+ * callback function is called with the complete message body if the message is
+ * complete.
+ *
+ * Symmetric callback is ERR, MSG, CLO only
+ * Asymmetric callback is OPN only
+ *
+ * @param channel the channel the chunks were received on.
+ * @param chunks the memory region where the chunks are stored.
+ * @param callback the callback function that gets called with the complete
+ * message body, once a final chunk is processed.
+ * @param application data pointer to application specific data that gets passed
+ * on to the callback function. */
+UA_StatusCode
+UA_SecureChannel_processChunk(UA_SecureChannel *channel, UA_ByteString *chunk,
+ UA_ProcessMessageCallback callback,
+ void *application,
+ UA_Boolean allowPreviousToken);
+
+/**
+ * Log Helper
+ * ----------
+ * C99 requires at least one element for the variadic argument. If the log
+ * statement has no variable arguments, supply an additional NULL. It will be
+ * ignored by printf.
+ *
+ * We have to jump through some hoops to enable the use of format strings
+ * without arguments since (pedantic) C99 does not allow variadic macros with
+ * zero arguments. So we add a dummy argument that is not printed (%.0s is
+ * string of length zero). */
+
+#define UA_LOG_TRACE_CHANNEL_INTERNAL(LOGGER, CHANNEL, MSG, ...) \
+ UA_LOG_TRACE(LOGGER, UA_LOGCATEGORY_SECURECHANNEL, \
+ "Connection %i | SecureChannel %i | " MSG "%.0s", \
+ ((CHANNEL)->connection ? (CHANNEL)->connection->sockfd : 0), \
+ (CHANNEL)->securityToken.channelId, __VA_ARGS__)
+
+#define UA_LOG_TRACE_CHANNEL(LOGGER, CHANNEL, ...) \
+ UA_MACRO_EXPAND(UA_LOG_TRACE_CHANNEL_INTERNAL(LOGGER, CHANNEL, __VA_ARGS__, ""))
+
+#define UA_LOG_DEBUG_CHANNEL_INTERNAL(LOGGER, CHANNEL, MSG, ...) \
+ UA_LOG_DEBUG(LOGGER, UA_LOGCATEGORY_SECURECHANNEL, \
+ "Connection %i | SecureChannel %i | " MSG "%.0s", \
+ ((CHANNEL)->connection ? (CHANNEL)->connection->sockfd : 0), \
+ (CHANNEL)->securityToken.channelId, __VA_ARGS__)
+
+#define UA_LOG_DEBUG_CHANNEL(LOGGER, CHANNEL, ...) \
+ UA_MACRO_EXPAND(UA_LOG_DEBUG_CHANNEL_INTERNAL(LOGGER, CHANNEL, __VA_ARGS__, ""))
+
+#define UA_LOG_INFO_CHANNEL_INTERNAL(LOGGER, CHANNEL, MSG, ...) \
+ UA_LOG_INFO(LOGGER, UA_LOGCATEGORY_SECURECHANNEL, \
+ "Connection %i | SecureChannel %i | " MSG "%.0s", \
+ ((CHANNEL)->connection ? (CHANNEL)->connection->sockfd : 0), \
+ (CHANNEL)->securityToken.channelId, __VA_ARGS__)
+
+#define UA_LOG_INFO_CHANNEL(LOGGER, CHANNEL, ...) \
+ UA_MACRO_EXPAND(UA_LOG_INFO_CHANNEL_INTERNAL(LOGGER, CHANNEL, __VA_ARGS__, ""))
+
+#define UA_LOG_WARNING_CHANNEL_INTERNAL(LOGGER, CHANNEL, MSG, ...) \
+ UA_LOG_WARNING(LOGGER, UA_LOGCATEGORY_SECURECHANNEL, \
+ "Connection %i | SecureChannel %i | " MSG "%.0s", \
+ ((CHANNEL)->connection ? (CHANNEL)->connection->sockfd : 0), \
+ (CHANNEL)->securityToken.channelId, __VA_ARGS__)
+
+#define UA_LOG_WARNING_CHANNEL(LOGGER, CHANNEL, ...) \
+ UA_MACRO_EXPAND(UA_LOG_WARNING_CHANNEL_INTERNAL(LOGGER, CHANNEL, __VA_ARGS__, ""))
+
+#define UA_LOG_ERROR_CHANNEL_INTERNAL(LOGGER, CHANNEL, MSG, ...) \
+ UA_LOG_ERROR(LOGGER, UA_LOGCATEGORY_SECURECHANNEL, \
+ "Connection %i | SecureChannel %i | " MSG "%.0s", \
+ ((CHANNEL)->connection ? (CHANNEL)->connection->sockfd : 0), \
+ (CHANNEL)->securityToken.channelId, __VA_ARGS__)
+
+#define UA_LOG_ERROR_CHANNEL(LOGGER, CHANNEL, ...) \
+ UA_MACRO_EXPAND(UA_LOG_ERROR_CHANNEL_INTERNAL(LOGGER, CHANNEL, __VA_ARGS__, ""))
+
+#define UA_LOG_FATAL_CHANNEL_INTERNAL(LOGGER, CHANNEL, MSG, ...) \
+ UA_LOG_FATAL(LOGGER, UA_LOGCATEGORY_SECURECHANNEL, \
+ "Connection %i | SecureChannel %i | " MSG "%.0s", \
+ ((CHANNEL)->connection ? (CHANNEL)->connection->sockfd : 0), \
+ (CHANNEL)->securityToken.channelId, __VA_ARGS__)
+
+#define UA_LOG_FATAL_CHANNEL(LOGGER, CHANNEL, ...) \
+ UA_MACRO_EXPAND(UA_LOG_FATAL_CHANNEL_INTERNAL(LOGGER, CHANNEL, __VA_ARGS__, ""))
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+
+/*********************************** amalgamated original file "/home/jvoe/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 (c) Julius Pfrommer, Fraunhofer IOSB
+ * Copyright 2017 (c) Stefan Profanter, fortiss GmbH
+ */
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/* An (event) timer triggers callbacks with a recurring interval. Adding,
+ * removing and changing repeated callbacks can be done from independent
+ * threads. Processing the changes and dispatching callbacks must be done by a
+ * single "mainloop" process.
+ * Timer callbacks with the same recurring interval are batched into blocks in
+ * order to reduce linear search for re-entry to the sorted list after processing.
+ * Callbacks are inserted in reversed order (last callback are put first in the block)
+ * to allow the monitored items of a subscription (if created in a sequence with the
+ * same publish/sample interval) to be executed before the subscription publish the
+ * notifications. When callbacks are entered to the timer list after execution they
+ * are added in the same order as before execution. */
+
+/* Forward declaration */
+struct UA_TimerCallbackEntry;
+typedef struct UA_TimerCallbackEntry UA_TimerCallbackEntry;
+
+/* Linked-list definition */
+typedef SLIST_HEAD(UA_TimerCallbackList, UA_TimerCallbackEntry) UA_TimerCallbackList;
+
+typedef struct {
+ /* The linked list of callbacks is sorted according to the execution timestamp. */
+ UA_TimerCallbackList repeatedCallbacks;
+
+ /* Changes to the repeated callbacks in a multi-producer single-consumer queue */
+ UA_TimerCallbackEntry * volatile changes_head;
+ UA_TimerCallbackEntry *changes_tail;
+ UA_TimerCallbackEntry *changes_stub;
+
+ UA_UInt64 idCounter;
+} UA_Timer;
+
+/* Initialize the Timer. Not thread-safe. */
+void UA_Timer_init(UA_Timer *t);
+
+/* Add a repated callback. Thread-safe, can be used in parallel and in parallel
+ * with UA_Timer_process. */
+typedef void (*UA_TimerCallback)(void *application, void *data);
+
+UA_StatusCode
+UA_Timer_addRepeatedCallback(UA_Timer *t, UA_TimerCallback callback, void *data,
+ UA_UInt32 interval, 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_UInt32 interval);
+
+/* Remove a repated callback. Thread-safe, can be used in parallel and in
+ * parallel with UA_Timer_process. */
+UA_StatusCode
+UA_Timer_removeRepeatedCallback(UA_Timer *t, UA_UInt64 callbackId);
+
+/* Process (dispatch) the repeated callbacks that have timed out. Returns the
+ * timestamp of the next scheduled repeated callback. Not thread-safe.
+ * Application is a pointer to the client / server environment for the callback.
+ * Dispatched is set to true when at least one callback was run / dispatched. */
+typedef void (*UA_TimerDispatchCallback)(void *application, UA_TimerCallback callback,
+ void *data);
+
+UA_DateTime
+UA_Timer_process(UA_Timer *t, UA_DateTime nowMonotonic,
+ UA_TimerDispatchCallback dispatchCallback,
+ void *application);
+
+/* Remove all repeated callbacks. Not thread-safe. */
+void UA_Timer_deleteMembers(UA_Timer *t);
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+
+/*********************************** amalgamated original file "/home/jvoe/open62541/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
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * Copyright 2018 (c) Julius Pfrommer, Fraunhofer IOSB
+ */
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+#define UA_MAXCONTINUATIONPOINTS 5
+
+typedef struct ContinuationPointEntry {
+ LIST_ENTRY(ContinuationPointEntry) pointers;
+ UA_ByteString identifier;
+ UA_BrowseDescription browseDescription;
+ UA_UInt32 maxReferences;
+
+ /* The last point in the node references? */
+ size_t referenceKindIndex;
+ size_t targetIndex;
+} ContinuationPointEntry;
+
+struct UA_Subscription;
+typedef struct UA_Subscription UA_Subscription;
+
+#ifdef UA_ENABLE_SUBSCRIPTIONS
+typedef struct UA_PublishResponseEntry {
+ SIMPLEQ_ENTRY(UA_PublishResponseEntry) listEntry;
+ UA_UInt32 requestId;
+ UA_PublishResponse response;
+} UA_PublishResponseEntry;
+#endif
+
+typedef struct {
+ UA_SessionHeader header;
+ UA_ApplicationDescription clientDescription;
+ UA_String sessionName;
+ UA_Boolean activated;
+ void *sessionHandle; // pointer assigned in userland-callback
+ UA_NodeId sessionId;
+ UA_UInt32 maxRequestMessageSize;
+ UA_UInt32 maxResponseMessageSize;
+ UA_Double timeout; // [ms]
+ UA_DateTime validTill;
+ UA_ByteString serverNonce;
+ UA_UInt16 availableContinuationPoints;
+ LIST_HEAD(ContinuationPointList, ContinuationPointEntry) continuationPoints;
+#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 */
+#endif
+} UA_Session;
+
+/**
+ * Session Lifecycle
+ * ----------------- */
+
+void UA_Session_init(UA_Session *session);
+void UA_Session_deleteMembersCleanup(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);
+
+/* If any activity on a session happens, the timeout is extended */
+void UA_Session_updateLifetime(UA_Session *session);
+
+/**
+ * Subscription handling
+ * --------------------- */
+
+#ifdef UA_ENABLE_SUBSCRIPTIONS
+
+void UA_Session_addSubscription(UA_Session *session, UA_Subscription *newSubscription);
+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, UA_PublishResponseEntry* entry, UA_Boolean head);
+UA_PublishResponseEntry* UA_Session_dequeuePublishReq(UA_Session *session);
+
+#endif
+
+/**
+ * Log Helper
+ * ----------
+ * We have to jump through some hoops to enable the use of format strings
+ * without arguments since (pedantic) C99 does not allow variadic macros with
+ * zero arguments. So we add a dummy argument that is not printed (%.0s is
+ * string of length zero). */
+
+#define UA_LOG_TRACE_SESSION_INTERNAL(LOGGER, SESSION, MSG, ...) \
+ UA_LOG_TRACE(LOGGER, UA_LOGCATEGORY_SESSION, \
+ "Connection %i | SecureChannel %i | Session " UA_PRINTF_GUID_FORMAT " | " MSG "%.0s", \
+ ((SESSION)->header.channel ? ((SESSION)->header.channel->connection ? (SESSION)->header.channel->connection->sockfd : 0) : 0), \
+ ((SESSION)->header.channel ? (SESSION)->header.channel->securityToken.channelId : 0), \
+ UA_PRINTF_GUID_DATA((SESSION)->sessionId.identifier.guid), __VA_ARGS__)
+
+#define UA_LOG_TRACE_SESSION(LOGGER, SESSION, ...) \
+ UA_MACRO_EXPAND(UA_LOG_TRACE_SESSION_INTERNAL(LOGGER, SESSION, __VA_ARGS__, ""))
+
+#define UA_LOG_DEBUG_SESSION_INTERNAL(LOGGER, SESSION, MSG, ...) \
+ UA_LOG_DEBUG(LOGGER, UA_LOGCATEGORY_SESSION, \
+ "Connection %i | SecureChannel %i | Session " UA_PRINTF_GUID_FORMAT " | " MSG "%.0s", \
+ ((SESSION)->header.channel ? ((SESSION)->header.channel->connection ? (SESSION)->header.channel->connection->sockfd : 0) : 0), \
+ ((SESSION)->header.channel ? (SESSION)->header.channel->securityToken.channelId : 0), \
+ UA_PRINTF_GUID_DATA((SESSION)->sessionId.identifier.guid), __VA_ARGS__)
+
+#define UA_LOG_DEBUG_SESSION(LOGGER, SESSION, ...) \
+ UA_MACRO_EXPAND(UA_LOG_DEBUG_SESSION_INTERNAL(LOGGER, SESSION, __VA_ARGS__, ""))
+
+#define UA_LOG_INFO_SESSION_INTERNAL(LOGGER, SESSION, MSG, ...) \
+ UA_LOG_INFO(LOGGER, UA_LOGCATEGORY_SESSION, \
+ "Connection %i | SecureChannel %i | Session " UA_PRINTF_GUID_FORMAT " | " MSG "%.0s", \
+ ((SESSION)->header.channel ? ((SESSION)->header.channel->connection ? (SESSION)->header.channel->connection->sockfd : 0) : 0), \
+ ((SESSION)->header.channel ? (SESSION)->header.channel->securityToken.channelId : 0), \
+ UA_PRINTF_GUID_DATA((SESSION)->sessionId.identifier.guid), __VA_ARGS__)
+
+#define UA_LOG_INFO_SESSION(LOGGER, SESSION, ...) \
+ UA_MACRO_EXPAND(UA_LOG_INFO_SESSION_INTERNAL(LOGGER, SESSION, __VA_ARGS__, ""))
+
+#define UA_LOG_WARNING_SESSION_INTERNAL(LOGGER, SESSION, MSG, ...) \
+ UA_LOG_WARNING(LOGGER, UA_LOGCATEGORY_SESSION, \
+ "Connection %i | SecureChannel %i | Session " UA_PRINTF_GUID_FORMAT " | " MSG "%.0s", \
+ ((SESSION)->header.channel ? ((SESSION)->header.channel->connection ? (SESSION)->header.channel->connection->sockfd : 0) : 0), \
+ ((SESSION)->header.channel ? (SESSION)->header.channel->securityToken.channelId : 0), \
+ UA_PRINTF_GUID_DATA((SESSION)->sessionId.identifier.guid), __VA_ARGS__)
+
+#define UA_LOG_WARNING_SESSION(LOGGER, SESSION, ...) \
+ UA_MACRO_EXPAND(UA_LOG_WARNING_SESSION_INTERNAL(LOGGER, SESSION, __VA_ARGS__, ""))
+
+#define UA_LOG_ERROR_SESSION_INTERNAL(LOGGER, SESSION, MSG, ...) \
+ UA_LOG_ERROR(LOGGER, UA_LOGCATEGORY_SESSION, \
+ "Connection %i | SecureChannel %i | Session " UA_PRINTF_GUID_FORMAT " | " MSG "%.0s", \
+ ((SESSION)->header.channel ? ((SESSION)->header.channel->connection ? (SESSION)->header.channel->connection->sockfd : 0) : 0), \
+ ((SESSION)->header.channel ? (SESSION)->header.channel->securityToken.channelId : 0), \
+ UA_PRINTF_GUID_DATA((SESSION)->sessionId.identifier.guid), __VA_ARGS__)
+
+#define UA_LOG_ERROR_SESSION(LOGGER, SESSION, ...) \
+ UA_MACRO_EXPAND(UA_LOG_ERROR_SESSION_INTERNAL(LOGGER, SESSION, __VA_ARGS__, ""))
+
+#define UA_LOG_FATAL_SESSION_INTERNAL(LOGGER, SESSION, MSG, ...) \
+ UA_LOG_FATAL(LOGGER, UA_LOGCATEGORY_SESSION, \
+ "Connection %i | SecureChannel %i | Session " UA_PRINTF_GUID_FORMAT " | " MSG "%.0s", \
+ ((SESSION)->header.channel ? ((SESSION)->header.channel->connection ? (SESSION)->header.channel->connection->sockfd : 0) : 0), \
+ ((SESSION)->header.channel ? (SESSION)->header.channel->securityToken.channelId : 0), \
+ UA_PRINTF_GUID_DATA((SESSION)->sessionId.identifier.guid), __VA_ARGS__)
+
+#define UA_LOG_FATAL_SESSION(LOGGER, SESSION, ...) \
+ UA_MACRO_EXPAND(UA_LOG_FATAL_SESSION_INTERNAL(LOGGER, SESSION, __VA_ARGS__, ""))
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+
+/*********************************** amalgamated original file "/home/jvoe/open62541/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-2017 (c) Julius Pfrommer, Fraunhofer IOSB
+ * Copyright 2015 (c) Chris Iatrou
+ * Copyright 2015-2016 (c) Sten Grüner
+ * Copyright 2015 (c) Oleksiy Vasylyev
+ * Copyright 2017 (c) Florian Palm
+ * Copyright 2017 (c) Stefan Profanter, fortiss GmbH
+ * Copyright 2017 (c) Mattias Bornhager
+ */
+
+
+
+/**
+ * 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
+ * MonitoredItem that generated the notification. Here we can remove it if the
+ * 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.
+ */
+
+/*****************/
+/* MonitoredItem */
+/*****************/
+
+typedef enum {
+ UA_MONITOREDITEMTYPE_CHANGENOTIFY = 1,
+ UA_MONITOREDITEMTYPE_STATUSNOTIFY = 2,
+ UA_MONITOREDITEMTYPE_EVENTNOTIFY = 4
+} UA_MonitoredItemType;
+
+/* Not used yet. Placeholder for a future event implementation. */
+typedef struct UA_Event {
+ UA_Int32 eventId;
+} UA_Event;
+
+struct UA_MonitoredItem;
+typedef struct UA_MonitoredItem UA_MonitoredItem;
+
+typedef struct UA_Notification {
+ TAILQ_ENTRY(UA_Notification) listEntry;
+ TAILQ_ENTRY(UA_Notification) globalEntry;
+
+ UA_MonitoredItem *mon;
+
+ /* See the monitoredItemType of the MonitoredItem */
+ union {
+ UA_Event event;
+ UA_DataValue value;
+ } data;
+} UA_Notification;
+
+typedef TAILQ_HEAD(NotificationQueue, UA_Notification) NotificationQueue;
+
+struct UA_MonitoredItem {
+ LIST_ENTRY(UA_MonitoredItem) listEntry;
+ UA_Subscription *subscription;
+ UA_UInt32 monitoredItemId;
+ UA_UInt32 clientHandle;
+
+ /* Settings */
+ UA_MonitoredItemType monitoredItemType;
+ UA_TimestampsToReturn timestampsToReturn;
+ UA_MonitoringMode monitoringMode;
+ UA_NodeId monitoredNodeId;
+ UA_UInt32 attributeId;
+ UA_String indexRange;
+ UA_Double samplingInterval; // [ms]
+ UA_UInt32 maxQueueSize;
+ UA_Boolean discardOldest;
+ // TODO: dataEncoding is hardcoded to UA binary
+ UA_DataChangeFilter filter;
+ UA_Variant lastValue;
+
+ /* Sample Callback */
+ UA_UInt64 sampleCallbackId;
+ UA_ByteString lastSampledValue;
+ UA_Boolean sampleCallbackIsRegistered;
+
+ /* Notification Queue */
+ NotificationQueue queue;
+ UA_UInt32 queueSize;
+};
+
+UA_MonitoredItem * UA_MonitoredItem_new(UA_MonitoredItemType);
+void MonitoredItem_delete(UA_Server *server, UA_MonitoredItem *monitoredItem);
+void UA_MonitoredItem_SampleCallback(UA_Server *server, UA_MonitoredItem *monitoredItem);
+UA_StatusCode MonitoredItem_registerSampleCallback(UA_Server *server, UA_MonitoredItem *mon);
+UA_StatusCode MonitoredItem_unregisterSampleCallback(UA_Server *server, UA_MonitoredItem *mon);
+
+/* Remove entries until mon->maxQueueSize is reached. Sets infobits for lost
+ * data if required. */
+void MonitoredItem_ensureQueueSpace(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 */
+ /* UA_SUBSCRIPTIONSTATE_CREATING */
+ UA_SUBSCRIPTIONSTATE_NORMAL,
+ UA_SUBSCRIPTIONSTATE_LATE,
+ UA_SUBSCRIPTIONSTATE_KEEPALIVE
+} UA_SubscriptionState;
+
+typedef TAILQ_HEAD(ListOfNotificationMessages, UA_NotificationMessageEntry) ListOfNotificationMessages;
+
+struct UA_Subscription {
+ LIST_ENTRY(UA_Subscription) listEntry;
+ UA_Session *session;
+ UA_UInt32 subscriptionId;
+
+ /* Settings */
+ UA_UInt32 lifeTimeCount;
+ UA_UInt32 maxKeepAliveCount;
+ UA_Double publishingInterval; /* in ms */
+ UA_UInt32 notificationsPerPublish;
+ UA_Boolean publishingEnabled;
+ UA_UInt32 priority;
+
+ /* Runtime information */
+ UA_SubscriptionState state;
+ UA_UInt32 nextSequenceNumber;
+ UA_UInt32 currentKeepAliveCount;
+ UA_UInt32 currentLifetimeCount;
+
+ /* Publish Callback */
+ UA_UInt64 publishCallbackId;
+ UA_Boolean publishCallbackIsRegistered;
+
+ /* MonitoredItems */
+ UA_UInt32 lastMonitoredItemId; /* increase the identifiers */
+ LIST_HEAD(UA_ListOfUAMonitoredItems, UA_MonitoredItem) monitoredItems;
+ UA_UInt32 monitoredItemsSize;
+
+ /* Global list of notifications from the MonitoredItems */
+ NotificationQueue notificationQueue;
+ UA_UInt32 notificationQueueSize;
+ UA_UInt32 readyNotifications; /* Notifications to be sent out now (already late) */
+
+ /* Retransmission Queue */
+ ListOfNotificationMessages retransmissionQueue;
+ size_t retransmissionQueueSize;
+};
+
+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);
+UA_StatusCode Subscription_unregisterPublishCallback(UA_Server *server, UA_Subscription *sub);
+void UA_Subscription_addMonitoredItem(UA_Subscription *sub, UA_MonitoredItem *newMon);
+UA_MonitoredItem * UA_Subscription_getMonitoredItem(UA_Subscription *sub, UA_UInt32 monitoredItemId);
+
+UA_StatusCode
+UA_Subscription_deleteMonitoredItem(UA_Server *server, UA_Subscription *sub,
+ UA_UInt32 monitoredItemId);
+
+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);
+
+
+/*********************************** amalgamated original file "/home/jvoe/open62541/src/server/ua_session_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
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * Copyright 2014-2017 (c) Julius Pfrommer, Fraunhofer IOSB
+ * Copyright 2014, 2017 (c) Florian Palm
+ * Copyright 2015 (c) Sten Grüner
+ * Copyright 2015 (c) Oleksiy Vasylyev
+ * Copyright 2017 (c) Stefan Profanter, fortiss GmbH
+ */
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+typedef struct session_list_entry {
+ LIST_ENTRY(session_list_entry) pointers;
+ UA_Session session;
+} session_list_entry;
+
+typedef struct UA_SessionManager {
+ LIST_HEAD(session_list, session_list_entry) sessions; // doubly-linked list of sessions
+ UA_UInt32 currentSessionCount;
+ UA_Server *server;
+} UA_SessionManager;
+
+UA_StatusCode
+UA_SessionManager_init(UA_SessionManager *sm, UA_Server *server);
+
+/* Deletes all sessions */
+void UA_SessionManager_deleteMembers(UA_SessionManager *sm);
+
+/* Deletes all sessions that have timed out. Deletion is implemented via a
+ * delayed callback. So all currently scheduled jobs with a pointer to the
+ * session can complete. */
+void UA_SessionManager_cleanupTimedOut(UA_SessionManager *sm,
+ UA_DateTime nowMonotonic);
+
+UA_StatusCode
+UA_SessionManager_createSession(UA_SessionManager *sm, UA_SecureChannel *channel,
+ const UA_CreateSessionRequest *request, UA_Session **session);
+
+UA_StatusCode
+UA_SessionManager_removeSession(UA_SessionManager *sm, const UA_NodeId *token);
+
+UA_Session *
+UA_SessionManager_getSessionByToken(UA_SessionManager *sm, const UA_NodeId *token);
+
+UA_Session *
+UA_SessionManager_getSessionById(UA_SessionManager *sm, const UA_NodeId *sessionId);
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+
+/*********************************** amalgamated original file "/home/jvoe/open62541/src/server/ua_securechannel_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
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * Copyright 2014-2017 (c) Julius Pfrommer, Fraunhofer IOSB
+ * Copyright 2014, 2017 (c) Florian Palm
+ * Copyright 2015 (c) Oleksiy Vasylyev
+ * Copyright 2017 (c) Stefan Profanter, fortiss GmbH
+ */
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+typedef struct channel_entry {
+ UA_SecureChannel channel;
+ TAILQ_ENTRY(channel_entry) pointers;
+} channel_entry;
+
+typedef struct {
+ TAILQ_HEAD(, channel_entry) channels; // doubly-linked list of channels
+ UA_UInt32 currentChannelCount;
+ UA_UInt32 lastChannelId;
+ UA_UInt32 lastTokenId;
+ UA_Server *server;
+} UA_SecureChannelManager;
+
+UA_StatusCode
+UA_SecureChannelManager_init(UA_SecureChannelManager *cm, UA_Server *server);
+
+/* Remove a all securechannels */
+void
+UA_SecureChannelManager_deleteMembers(UA_SecureChannelManager *cm);
+
+/* Remove timed out securechannels with a delayed callback. So all currently
+ * scheduled jobs with a pointer to a securechannel can finish first. */
+void
+UA_SecureChannelManager_cleanupTimedOut(UA_SecureChannelManager *cm,
+ UA_DateTime nowMonotonic);
+
+UA_StatusCode
+UA_SecureChannelManager_create(UA_SecureChannelManager *const cm, UA_Connection *const connection,
+ const UA_SecurityPolicy *const securityPolicy,
+ const UA_AsymmetricAlgorithmSecurityHeader *const asymHeader);
+
+UA_StatusCode
+UA_SecureChannelManager_open(UA_SecureChannelManager *cm, UA_SecureChannel *channel,
+ const UA_OpenSecureChannelRequest *request,
+ UA_OpenSecureChannelResponse *response);
+
+UA_StatusCode
+UA_SecureChannelManager_renew(UA_SecureChannelManager *cm, UA_SecureChannel *channel,
+ const UA_OpenSecureChannelRequest *request,
+ UA_OpenSecureChannelResponse *response);
+
+UA_SecureChannel *
+UA_SecureChannelManager_get(UA_SecureChannelManager *cm, UA_UInt32 channelId);
+
+UA_StatusCode
+UA_SecureChannelManager_close(UA_SecureChannelManager *cm, UA_UInt32 channelId);
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+
+/*********************************** amalgamated original file "/home/jvoe/open62541/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
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * Copyright 2014-2017 (c) Julius Pfrommer, Fraunhofer IOSB
+ * Copyright 2014, 2017 (c) Florian Palm
+ * Copyright 2015-2016 (c) Sten Grüner
+ * Copyright 2015 (c) Chris Iatrou
+ * Copyright 2015-2016 (c) Oleksiy Vasylyev
+ * Copyright 2016-2017 (c) Stefan Profanter, fortiss GmbH
+ * Copyright 2017 (c) Julian Grothoff
+ */
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+#ifdef UA_ENABLE_MULTITHREADING
+
+#include <pthread.h>
+
+struct UA_Worker;
+typedef struct UA_Worker UA_Worker;
+
+struct UA_WorkerCallback;
+typedef struct UA_WorkerCallback UA_WorkerCallback;
+
+SIMPLEQ_HEAD(UA_DispatchQueue, UA_WorkerCallback);
+typedef struct UA_DispatchQueue UA_DispatchQueue;
+
+#endif /* UA_ENABLE_MULTITHREADING */
+
+#ifdef UA_ENABLE_DISCOVERY
+
+typedef struct registeredServer_list_entry {
+ LIST_ENTRY(registeredServer_list_entry) pointers;
+ UA_RegisteredServer registeredServer;
+ UA_DateTime lastSeen;
+} registeredServer_list_entry;
+
+typedef struct periodicServerRegisterCallback_entry {
+ LIST_ENTRY(periodicServerRegisterCallback_entry) pointers;
+ struct PeriodicServerRegisterCallback *callback;
+} periodicServerRegisterCallback_entry;
+
+#ifdef UA_ENABLE_DISCOVERY_MULTICAST
+
+
+typedef struct serverOnNetwork_list_entry {
+ LIST_ENTRY(serverOnNetwork_list_entry) pointers;
+ UA_ServerOnNetwork serverOnNetwork;
+ UA_DateTime created;
+ UA_DateTime lastSeen;
+ UA_Boolean txtSet;
+ UA_Boolean srvSet;
+ char* pathTmp;
+} serverOnNetwork_list_entry;
+
+#define SERVER_ON_NETWORK_HASH_PRIME 1009
+typedef struct serverOnNetwork_hash_entry {
+ serverOnNetwork_list_entry* entry;
+ struct serverOnNetwork_hash_entry* next;
+} serverOnNetwork_hash_entry;
+
+#endif /* UA_ENABLE_DISCOVERY_MULTICAST */
+#endif /* UA_ENABLE_DISCOVERY */
+
+struct UA_Server {
+ /* Meta */
+ UA_DateTime startTime;
+
+ /* Security */
+ UA_SecureChannelManager secureChannelManager;
+ UA_SessionManager sessionManager;
+
+#ifdef UA_ENABLE_DISCOVERY
+ /* Discovery */
+ LIST_HEAD(registeredServer_list, registeredServer_list_entry) registeredServers; // doubly-linked list of registered servers
+ size_t registeredServersSize;
+ LIST_HEAD(periodicServerRegisterCallback_list, periodicServerRegisterCallback_entry) periodicServerRegisterCallbacks; // doubly-linked list of current register callbacks
+ UA_Server_registerServerCallback registerServerCallback;
+ void* registerServerCallbackData;
+# ifdef UA_ENABLE_DISCOVERY_MULTICAST
+ mdns_daemon_t *mdnsDaemon;
+#ifdef _WIN32
+ SOCKET mdnsSocket;
+#else
+ int mdnsSocket;
+#endif
+ UA_Boolean mdnsMainSrvAdded;
+# ifdef UA_ENABLE_MULTITHREADING
+ pthread_t mdnsThread;
+ UA_Boolean mdnsRunning;
+# endif
+
+ LIST_HEAD(serverOnNetwork_list, serverOnNetwork_list_entry) serverOnNetwork; // doubly-linked list of servers on the network (from mDNS)
+ size_t serverOnNetworkSize;
+ UA_UInt32 serverOnNetworkRecordIdCounter;
+ UA_DateTime serverOnNetworkRecordIdLastReset;
+ // hash mapping domain name to serverOnNetwork list entry
+ struct serverOnNetwork_hash_entry* serverOnNetworkHash[SERVER_ON_NETWORK_HASH_PRIME];
+
+ UA_Server_serverOnNetworkCallback serverOnNetworkCallback;
+ void* serverOnNetworkCallbackData;
+
+# endif
+#endif
+
+ /* Namespaces */
+ size_t namespacesSize;
+ UA_String *namespaces;
+
+ /* Callbacks with a repetition interval */
+ UA_Timer timer;
+
+ /* Delayed callbacks */
+ SLIST_HEAD(DelayedCallbacksList, UA_DelayedCallback) delayedCallbacks;
+
+ /* Worker threads */
+#ifdef UA_ENABLE_MULTITHREADING
+ UA_Worker *workers; /* there are nThread workers in a running server */
+ UA_DispatchQueue dispatchQueue; /* Dispatch queue for the worker threads */
+ pthread_mutex_t dispatchQueue_accessMutex; /* mutex for access to queue */
+ pthread_cond_t dispatchQueue_condition; /* so the workers don't spin if the queue is empty */
+ pthread_mutex_t dispatchQueue_conditionMutex; /* mutex for access to condition variable */
+#endif
+
+ /* For bootstrapping, omit some consistency checks, creating a reference to
+ * the parent and member instantiation */
+ UA_Boolean bootstrapNS0;
+
+ /* Config */
+ UA_ServerConfig config;
+
+ /* Local access to the services (for startup and maintenance) uses this
+ * Session with all possible access rights (Session Id: 1) */
+ UA_Session adminSession;
+};
+
+/*****************/
+/* Node Handling */
+/*****************/
+
+#define UA_Nodestore_get(SERVER, NODEID) \
+ (SERVER)->config.nodestore.getNode((SERVER)->config.nodestore.context, NODEID)
+
+#define UA_Nodestore_release(SERVER, NODEID) \
+ (SERVER)->config.nodestore.releaseNode((SERVER)->config.nodestore.context, NODEID)
+
+#define UA_Nodestore_new(SERVER, NODECLASS) \
+ (SERVER)->config.nodestore.newNode((SERVER)->config.nodestore.context, NODECLASS)
+
+#define UA_Nodestore_getCopy(SERVER, NODEID, OUTNODE) \
+ (SERVER)->config.nodestore.getNodeCopy((SERVER)->config.nodestore.context, NODEID, OUTNODE)
+
+#define UA_Nodestore_insert(SERVER, NODE, OUTNODEID) \
+ (SERVER)->config.nodestore.insertNode((SERVER)->config.nodestore.context, NODE, OUTNODEID)
+
+#define UA_Nodestore_delete(SERVER, NODE) \
+ (SERVER)->config.nodestore.deleteNode((SERVER)->config.nodestore.context, NODE)
+
+#define UA_Nodestore_remove(SERVER, NODEID) \
+ (SERVER)->config.nodestore.removeNode((SERVER)->config.nodestore.context, NODEID)
+
+/* 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.*/
+typedef UA_StatusCode (*UA_EditNodeCallback)(UA_Server*, UA_Session*,
+ UA_Node *node, void*);
+UA_StatusCode UA_Server_editNode(UA_Server *server, UA_Session *session,
+ const UA_NodeId *nodeId,
+ UA_EditNodeCallback callback,
+ void *data);
+
+/*************/
+/* Callbacks */
+/*************/
+
+/* Delayed callbacks are executed when all previously dispatched callbacks are
+ * finished */
+UA_StatusCode
+UA_Server_delayedCallback(UA_Server *server, UA_ServerCallback callback, void *data);
+
+UA_StatusCode
+UA_Server_delayedFree(UA_Server *server, void *data);
+
+#ifndef UA_ENABLE_MULTITHREADING
+/* Execute all delayed callbacks regardless of whether the worker threads have
+ * finished previous work */
+void UA_Server_cleanupDelayedCallbacks(UA_Server *server);
+#else
+void UA_Server_cleanupDispatchQueue(UA_Server *server);
+#endif
+
+/* Callback is executed in the same thread or, if possible, dispatched to one of
+ * the worker threads. */
+void
+UA_Server_workerCallback(UA_Server *server, UA_ServerCallback callback, void *data);
+
+/*********************/
+/* Utility Functions */
+/*********************/
+
+/* A few global NodeId definitions */
+extern const UA_NodeId subtypeId;
+
+UA_StatusCode
+UA_NumericRange_parseFromString(UA_NumericRange *range, const UA_String *str);
+
+UA_UInt16 addNamespace(UA_Server *server, const UA_String name);
+
+UA_Boolean
+UA_Node_hasSubTypeOrInstances(const UA_Node *node);
+
+/* Recursively searches "upwards" in the tree following specific reference types */
+UA_Boolean
+isNodeInTree(UA_Nodestore *ns, const UA_NodeId *leafNode,
+ const UA_NodeId *nodeToFind, const UA_NodeId *referenceTypeIds,
+ size_t referenceTypeIdsSize);
+
+/* Returns an array with the hierarchy of type nodes. The returned array starts
+ * at the leaf and continues "upwards" in the hierarchy based on the
+ * ``hasSubType`` references. Since multiple-inheritance is possible in general,
+ * duplicate entries are removed. */
+UA_StatusCode
+getTypeHierarchy(UA_Nodestore *ns, const UA_NodeId *leafType,
+ UA_NodeId **typeHierarchy, size_t *typeHierarchySize);
+
+/* 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);
+
+/* Many services come as an array of operations. This function generalizes the
+ * processing of the operations. */
+typedef void (*UA_ServiceOperation)(UA_Server *server, UA_Session *session,
+ void *context,
+ const void *requestOperation,
+ void *responseOperation);
+
+UA_StatusCode
+UA_Server_processServiceOperations(UA_Server *server, UA_Session *session,
+ UA_ServiceOperation operationCallback,
+ void *context,
+ const size_t *requestOperations,
+ const UA_DataType *requestOperationsType,
+ size_t *responseOperations,
+ const UA_DataType *responseOperationsType)
+ UA_FUNC_ATTR_WARN_UNUSED_RESULT;
+
+/***************************************/
+/* Check Information Model Consistency */
+/***************************************/
+
+UA_StatusCode
+readValueAttribute(UA_Server *server, UA_Session *session,
+ const UA_VariableNode *vn, UA_DataValue *v);
+
+/* Test whether the value matches a variable definition given by
+ * - datatype
+ * - valueranke
+ * - 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. */
+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);
+
+UA_Boolean
+compatibleArrayDimensions(size_t constraintArrayDimensionsSize,
+ const UA_UInt32 *constraintArrayDimensions,
+ size_t testArrayDimensionsSize,
+ const UA_UInt32 *testArrayDimensions);
+
+UA_Boolean
+compatibleValueArrayDimensions(const UA_Variant *value, size_t targetArrayDimensionsSize,
+ const UA_UInt32 *targetArrayDimensions);
+
+UA_Boolean
+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);
+
+void
+Operation_Browse(UA_Server *server, UA_Session *session, UA_UInt32 *maxrefs,
+ const UA_BrowseDescription *descr, UA_BrowseResult *result);
+
+UA_DataValue
+UA_Server_readWithSession(UA_Server *server, UA_Session *session,
+ const UA_ReadValueId *item,
+ UA_TimestampsToReturn timestampsToReturn);
+
+/* Checks if a registration timed out and removes that registration.
+ * Should be called periodically in main loop */
+void UA_Discovery_cleanupTimedOut(UA_Server *server, UA_DateTime nowMonotonic);
+
+# ifdef UA_ENABLE_DISCOVERY_MULTICAST
+
+UA_StatusCode
+initMulticastDiscoveryServer(UA_Server* server);
+
+void startMulticastDiscoveryServer(UA_Server *server);
+
+void stopMulticastDiscoveryServer(UA_Server *server);
+
+UA_StatusCode
+iterateMulticastDiscoveryServer(UA_Server* server, UA_DateTime *nextRepeat,
+ UA_Boolean processIn);
+
+void destroyMulticastDiscoveryServer(UA_Server* server);
+
+typedef enum {
+ UA_DISCOVERY_TCP, /* OPC UA TCP mapping */
+ UA_DISCOVERY_TLS /* OPC UA HTTPS mapping */
+} UA_DiscoveryProtocol;
+
+/* Send a multicast probe to find any other OPC UA server on the network through mDNS. */
+UA_StatusCode
+UA_Discovery_multicastQuery(UA_Server* server);
+
+UA_StatusCode
+UA_Discovery_addRecord(UA_Server *server, const UA_String *servername,
+ const UA_String *hostname, UA_UInt16 port,
+ const UA_String *path, const UA_DiscoveryProtocol protocol,
+ UA_Boolean createTxt, const UA_String* capabilites,
+ size_t *capabilitiesSize);
+UA_StatusCode
+UA_Discovery_removeRecord(UA_Server *server, const UA_String *servername,
+ const UA_String *hostname, UA_UInt16 port,
+ UA_Boolean removeTxt);
+
+# endif
+
+/*****************************/
+/* AddNodes Begin and Finish */
+/*****************************/
+
+/* Creates a new node in the nodestore. */
+UA_StatusCode
+Operation_addNode_begin(UA_Server *server, UA_Session *session, void *nodeContext,
+ const UA_AddNodesItem *item, const UA_NodeId *parentNodeId,
+ const UA_NodeId *referenceTypeId,
+ UA_NodeId *outNewNodeId);
+
+/* Children, references, type-checking, constructors. */
+UA_StatusCode
+Operation_addNode_finish(UA_Server *server, UA_Session *session,
+ const UA_NodeId *nodeId);
+
+/**********************/
+/* Create Namespace 0 */
+/**********************/
+
+UA_StatusCode UA_Server_initNS0(UA_Server *server);
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+
+/*********************************** amalgamated original file "/home/jvoe/open62541/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
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * Copyright 2014-2017 (c) Julius Pfrommer, Fraunhofer IOSB
+ * Copyright 2014-2017 (c) Florian Palm
+ * Copyright 2015 (c) Sten Grüner
+ * Copyright 2014 (c) LEvertz
+ * Copyright 2015 (c) Chris Iatrou
+ * Copyright 2015 (c) Christian Fimmers
+ * Copyright 2015-2016 (c) Oleksiy Vasylyev
+ * Copyright 2017 (c) Stefan Profanter, fortiss GmbH
+ */
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/**
+ * .. _services:
+ *
+ * Services
+ * ========
+ *
+ * In OPC UA, all communication is based on service calls, each consisting of a
+ * request and a response message. These messages are defined as data structures
+ * with a binary encoding and listed in :ref:`generated-types`. Since all
+ * Services are pre-defined in the standard, they cannot be modified by the
+ * user. But you can use the :ref:`Call <method-services>` service to invoke
+ * user-defined methods on the server.
+ *
+ * The following service signatures are internal and *not visible to users*.
+ * Still, we present them here for an overview of the capabilities of OPC UA.
+ * Please refer to the :ref:`client` and :ref:`server` API where the services
+ * are exposed to end users. Please see part 4 of the OPC UA standard for the
+ * authoritative definition of the service and their behaviour.
+ *
+ * Most services take as input the server, the current session and pointers to
+ * the request and response structures. Possible error codes are returned as
+ * part of the response. */
+
+typedef void (*UA_Service)(UA_Server*, UA_Session*,
+ const void *request, void *response);
+
+typedef UA_StatusCode (*UA_InSituService)(UA_Server*, UA_Session*, UA_MessageContext *mc,
+ const void *request, UA_ResponseHeader *rh);
+
+/**
+ * Discovery Service Set
+ * ---------------------
+ * This Service Set defines Services used to discover the Endpoints implemented
+ * by a Server and to read the security configuration for those Endpoints.
+ *
+ * FindServers Service
+ * ^^^^^^^^^^^^^^^^^^^
+ * Returns the Servers known to a Server or Discovery Server. The Client may
+ * reduce the number of results returned by specifying filter criteria */
+void Service_FindServers(UA_Server *server, UA_Session *session,
+ const UA_FindServersRequest *request,
+ UA_FindServersResponse *response);
+
+/**
+ * GetEndpoints Service
+ * ^^^^^^^^^^^^^^^^^^^^
+ * Returns the Endpoints supported by a Server and all of the configuration
+ * information required to establish a SecureChannel and a Session. */
+void Service_GetEndpoints(UA_Server *server, UA_Session *session,
+ const UA_GetEndpointsRequest *request,
+ UA_GetEndpointsResponse *response);
+
+#ifdef UA_ENABLE_DISCOVERY
+
+# ifdef UA_ENABLE_DISCOVERY_MULTICAST
+
+/**
+ * FindServersOnNetwork Service
+ * ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ * Returns the Servers known to a Discovery Server. Unlike FindServer,
+ * this Service is only implemented by Discovery Servers. It additionally
+ * Returns servery which may have been detected trough Multicast */
+void Service_FindServersOnNetwork(UA_Server *server, UA_Session *session,
+ const UA_FindServersOnNetworkRequest *request,
+ UA_FindServersOnNetworkResponse *response);
+
+# endif /* UA_ENABLE_DISCOVERY_MULTICAST */
+
+/**
+ * RegisterServer
+ * ^^^^^^^^^^^^^^
+ * Registers a remote server in the local discovery service. */
+void Service_RegisterServer(UA_Server *server, UA_Session *session,
+ const UA_RegisterServerRequest *request,
+ UA_RegisterServerResponse *response);
+
+/**
+ * RegisterServer2
+ * ^^^^^^^^^^^^^^^
+ * This Service allows a Server to register its DiscoveryUrls and capabilities
+ * with a Discovery Server. It extends the registration information from
+ * RegisterServer with information necessary for FindServersOnNetwork. */
+void Service_RegisterServer2(UA_Server *server, UA_Session *session,
+ const UA_RegisterServer2Request *request,
+ UA_RegisterServer2Response *response);
+
+#endif /* UA_ENABLE_DISCOVERY */
+
+/**
+ * SecureChannel Service Set
+ * -------------------------
+ * This Service Set defines Services used to open a communication channel that
+ * ensures the confidentiality and Integrity of all Messages exchanged with the
+ * Server.
+ *
+ * OpenSecureChannel Service
+ * ^^^^^^^^^^^^^^^^^^^^^^^^^
+ * Open or renew a SecureChannel that can be used to ensure Confidentiality and
+ * Integrity for Message exchange during a Session. */
+void Service_OpenSecureChannel(UA_Server *server, UA_SecureChannel* channel,
+ const UA_OpenSecureChannelRequest *request,
+ UA_OpenSecureChannelResponse *response);
+
+/**
+ * CloseSecureChannel Service
+ * ^^^^^^^^^^^^^^^^^^^^^^^^^^
+ * Used to terminate a SecureChannel. */
+void Service_CloseSecureChannel(UA_Server *server, UA_SecureChannel *channel);
+
+/**
+ * Session Service Set
+ * -------------------
+ * This Service Set defines Services for an application layer connection
+ * establishment in the context of a Session.
+ *
+ * CreateSession Service
+ * ^^^^^^^^^^^^^^^^^^^^^
+ * Used by an OPC UA Client to create a Session and the Server returns two
+ * values which uniquely identify the Session. The first value is the sessionId
+ * which is used to identify the Session in the audit logs and in the Server's
+ * address space. The second is the authenticationToken which is used to
+ * associate an incoming request with a Session. */
+void Service_CreateSession(UA_Server *server, UA_SecureChannel *channel,
+ const UA_CreateSessionRequest *request,
+ UA_CreateSessionResponse *response);
+
+/**
+ * ActivateSession
+ * ^^^^^^^^^^^^^^^
+ * Used by the Client to submit its SoftwareCertificates to the Server for
+ * validation and to specify the identity of the user associated with the
+ * Session. This Service request shall be issued by the Client before it issues
+ * any other Service request after CreateSession. Failure to do so shall cause
+ * the Server to close the Session. */
+void Service_ActivateSession(UA_Server *server, UA_SecureChannel *channel,
+ UA_Session *session,
+ const UA_ActivateSessionRequest *request,
+ UA_ActivateSessionResponse *response);
+
+/**
+ * CloseSession
+ * ^^^^^^^^^^^^
+ * Used to terminate a Session. */
+void Service_CloseSession(UA_Server *server, UA_Session *session,
+ const UA_CloseSessionRequest *request,
+ UA_CloseSessionResponse *response);
+
+/**
+ * Cancel Service
+ * ^^^^^^^^^^^^^^
+ * Used to cancel outstanding Service requests. Successfully cancelled service
+ * requests shall respond with Bad_RequestCancelledByClient. */
+/* Not Implemented */
+
+/**
+ * NodeManagement Service Set
+ * --------------------------
+ * This Service Set defines Services to add and delete AddressSpace Nodes and
+ * References between them. All added Nodes continue to exist in the
+ * AddressSpace even if the Client that created them disconnects from the
+ * Server.
+ *
+ * AddNodes Service
+ * ^^^^^^^^^^^^^^^^
+ * Used to add one or more Nodes into the AddressSpace hierarchy. */
+void Service_AddNodes(UA_Server *server, UA_Session *session,
+ const UA_AddNodesRequest *request,
+ UA_AddNodesResponse *response);
+
+/**
+ * AddReferences Service
+ * ^^^^^^^^^^^^^^^^^^^^^
+ * 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);
+
+/**
+ * DeleteNodes Service
+ * ^^^^^^^^^^^^^^^^^^^
+ * Used to delete one or more Nodes from the AddressSpace. */
+void Service_DeleteNodes(UA_Server *server, UA_Session *session,
+ const UA_DeleteNodesRequest *request,
+ UA_DeleteNodesResponse *response);
+
+/**
+ * DeleteReferences
+ * ^^^^^^^^^^^^^^^^
+ * Used to delete one or more References of a Node. */
+void Service_DeleteReferences(UA_Server *server, UA_Session *session,
+ const UA_DeleteReferencesRequest *request,
+ UA_DeleteReferencesResponse *response);
+
+/**
+ * .. _view-services:
+ *
+ * View Service Set
+ * ----------------
+ * Clients use the browse Services of the View Service Set to navigate through
+ * the AddressSpace or through a View which is a subset of the AddressSpace.
+ *
+ * Browse Service
+ * ^^^^^^^^^^^^^^
+ * Used to discover the References of a specified Node. The browse can be
+ * further limited by the use of a View. This Browse Service also supports a
+ * primitive filtering capability. */
+void Service_Browse(UA_Server *server, UA_Session *session,
+ const UA_BrowseRequest *request,
+ UA_BrowseResponse *response);
+
+/**
+ * BrowseNext Service
+ * ^^^^^^^^^^^^^^^^^^
+ * Used to request the next set of Browse or BrowseNext response information
+ * that is too large to be sent in a single response. "Too large" in this
+ * context means that the Server is not able to return a larger response or that
+ * the number of results to return exceeds the maximum number of results to
+ * return that was specified by the Client in the original Browse request. */
+void Service_BrowseNext(UA_Server *server, UA_Session *session,
+ const UA_BrowseNextRequest *request,
+ UA_BrowseNextResponse *response);
+
+/**
+ * TranslateBrowsePathsToNodeIds Service
+ * ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ * Used to translate textual node paths to their respective ids. */
+void Service_TranslateBrowsePathsToNodeIds(UA_Server *server, UA_Session *session,
+ const UA_TranslateBrowsePathsToNodeIdsRequest *request,
+ UA_TranslateBrowsePathsToNodeIdsResponse *response);
+
+/**
+ * RegisterNodes Service
+ * ^^^^^^^^^^^^^^^^^^^^^
+ * Used by Clients to register the Nodes that they know they will access
+ * repeatedly (e.g. Write, Call). It allows Servers to set up anything needed so
+ * that the access operations will be more efficient. */
+void Service_RegisterNodes(UA_Server *server, UA_Session *session,
+ const UA_RegisterNodesRequest *request,
+ UA_RegisterNodesResponse *response);
+
+/**
+ * UnregisterNodes Service
+ * ^^^^^^^^^^^^^^^^^^^^^^^
+ * This Service is used to unregister NodeIds that have been obtained via the
+ * RegisterNodes service. */
+void Service_UnregisterNodes(UA_Server *server, UA_Session *session,
+ const UA_UnregisterNodesRequest *request,
+ UA_UnregisterNodesResponse *response);
+
+/**
+ * Query Service Set
+ * -----------------
+ * This Service Set is used to issue a Query to a Server. OPC UA Query is
+ * generic in that it provides an underlying storage mechanism independent Query
+ * capability that can be used to access a wide variety of OPC UA data stores
+ * and information management systems. OPC UA Query permits a Client to access
+ * data maintained by a Server without any knowledge of the logical schema used
+ * for internal storage of the data. Knowledge of the AddressSpace is
+ * sufficient.
+ *
+ * QueryFirst Service
+ * ^^^^^^^^^^^^^^^^^^
+ * This Service is used to issue a Query request to the Server. */
+/* Not Implemented */
+
+/**
+ * QueryNext Service
+ * ^^^^^^^^^^^^^^^^^
+ * This Service is used to request the next set of QueryFirst or QueryNext
+ * response information that is too large to be sent in a single response. */
+/* Not Impelemented */
+
+/**
+ * Attribute Service Set
+ * ---------------------
+ * This Service Set provides Services to access Attributes that are part of
+ * Nodes.
+ *
+ * Read Service
+ * ^^^^^^^^^^^^
+ * Used to read attributes of nodes. For constructed attribute values whose
+ * elements are indexed, such as an array, this Service allows Clients to read
+ * the entire set of indexed values as a composite, to read individual elements
+ * or to read ranges of elements of the composite. */
+UA_StatusCode Service_Read(UA_Server *server, UA_Session *session, UA_MessageContext *mc,
+ const UA_ReadRequest *request, UA_ResponseHeader *responseHeader);
+
+/**
+ * Write Service
+ * ^^^^^^^^^^^^^
+ * Used to write attributes of nodes. For constructed attribute values whose
+ * elements are indexed, such as an array, this Service allows Clients to write
+ * the entire set of indexed values as a composite, to write individual elements
+ * or to write ranges of elements of the composite. */
+void Service_Write(UA_Server *server, UA_Session *session,
+ const UA_WriteRequest *request,
+ UA_WriteResponse *response);
+
+/**
+ * HistoryRead Service
+ * ^^^^^^^^^^^^^^^^^^^
+ * Used to read historical values or Events of one or more Nodes. Servers may
+ * make historical values available to Clients using this Service, although the
+ * historical values themselves are not visible in the AddressSpace. */
+/* Not Implemented */
+
+/**
+ * HistoryUpdate Service
+ * ^^^^^^^^^^^^^^^^^^^^^
+ * Used to update historical values or Events of one or more Nodes. Several
+ * request parameters indicate how the Server is to update the historical value
+ * or Event. Valid actions are Insert, Replace or Delete. */
+/* Not Implemented */
+
+/**
+ * .. _method-services:
+ *
+ * Method Service Set
+ * ------------------
+ * The Method Service Set defines the means to invoke methods. A method shall be
+ * a component of an Object. See the section on :ref:`MethodNodes <methodnode>`
+ * for more information.
+ *
+ * Call Service
+ * ^^^^^^^^^^^^
+ * Used to call (invoke) a methods. Each method call is invoked within the
+ * context of an existing Session. If the Session is terminated, the results of
+ * the method's execution cannot be returned to the Client and are discarded. */
+void Service_Call(UA_Server *server, UA_Session *session,
+ const UA_CallRequest *request,
+ UA_CallResponse *response);
+
+/**
+ * MonitoredItem Service Set
+ * -------------------------
+ * Clients define MonitoredItems to subscribe to data and Events. Each
+ * MonitoredItem identifies the item to be monitored and the Subscription to use
+ * to send Notifications. The item to be monitored may be any Node Attribute.
+ *
+ * CreateMonitoredItems Service
+ * ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ * Used to create and add one or more MonitoredItems to a Subscription. A
+ * MonitoredItem is deleted automatically by the Server when the Subscription is
+ * deleted. Deleting a MonitoredItem causes its entire set of triggered item
+ * links to be deleted, but has no effect on the MonitoredItems referenced by
+ * the triggered items. */
+void Service_CreateMonitoredItems(UA_Server *server, UA_Session *session,
+ const UA_CreateMonitoredItemsRequest *request,
+ UA_CreateMonitoredItemsResponse *response);
+
+/**
+ * DeleteMonitoredItems Service
+ * ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ * Used to remove one or more MonitoredItems of a Subscription. When a
+ * MonitoredItem is deleted, its triggered item links are also deleted. */
+void Service_DeleteMonitoredItems(UA_Server *server, UA_Session *session,
+ const UA_DeleteMonitoredItemsRequest *request,
+ UA_DeleteMonitoredItemsResponse *response);
+
+/**
+ * ModifyMonitoredItems Service
+ * ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ * Used to modify MonitoredItems of a Subscription. Changes to the MonitoredItem
+ * settings shall be applied immediately by the Server. They take effect as soon
+ * as practical but not later than twice the new revisedSamplingInterval.
+ *
+ * Illegal request values for parameters that can be revised do not generate
+ * errors. Instead the server will choose default values and indicate them in
+ * the corresponding revised parameter. */
+void Service_ModifyMonitoredItems(UA_Server *server, UA_Session *session,
+ const UA_ModifyMonitoredItemsRequest *request,
+ UA_ModifyMonitoredItemsResponse *response);
+
+/**
+ * SetMonitoringMode Service
+ * ^^^^^^^^^^^^^^^^^^^^^^^^^
+ * Used to set the monitoring mode for one or more MonitoredItems of a
+ * Subscription. */
+void Service_SetMonitoringMode(UA_Server *server, UA_Session *session,
+ const UA_SetMonitoringModeRequest *request,
+ UA_SetMonitoringModeResponse *response);
+
+/**
+ * SetTriggering Service
+ * ^^^^^^^^^^^^^^^^^^^^^
+ * Used to create and delete triggering links for a triggering item. */
+/* Not Implemented */
+
+/**
+ * Subscription Service Set
+ * ------------------------
+ * Subscriptions are used to report Notifications to the Client.
+ *
+ * CreateSubscription Service
+ * ^^^^^^^^^^^^^^^^^^^^^^^^^^
+ * Used to create a Subscription. Subscriptions monitor a set of MonitoredItems
+ * for Notifications and return them to the Client in response to Publish
+ * requests. */
+void Service_CreateSubscription(UA_Server *server, UA_Session *session,
+ const UA_CreateSubscriptionRequest *request,
+ UA_CreateSubscriptionResponse *response);
+
+/**
+ * ModifySubscription Service
+ * ^^^^^^^^^^^^^^^^^^^^^^^^^^
+ * Used to modify a Subscription. */
+void Service_ModifySubscription(UA_Server *server, UA_Session *session,
+ const UA_ModifySubscriptionRequest *request,
+ UA_ModifySubscriptionResponse *response);
+
+/**
+ * SetPublishingMode Service
+ * ^^^^^^^^^^^^^^^^^^^^^^^^^
+ * Used to enable sending of Notifications on one or more Subscriptions. */
+void Service_SetPublishingMode(UA_Server *server, UA_Session *session,
+ const UA_SetPublishingModeRequest *request,
+ UA_SetPublishingModeResponse *response);
+
+/**
+ * Publish Service
+ * ^^^^^^^^^^^^^^^
+ * Used for two purposes. First, it is used to acknowledge the receipt of
+ * NotificationMessages for one or more Subscriptions. Second, it is used to
+ * request the Server to return a NotificationMessage or a keep-alive
+ * Message.
+ *
+ * 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);
+
+/**
+ * Republish Service
+ * ^^^^^^^^^^^^^^^^^
+ * Requests the Subscription to republish a NotificationMessage from its
+ * retransmission queue. */
+void Service_Republish(UA_Server *server, UA_Session *session,
+ const UA_RepublishRequest *request,
+ UA_RepublishResponse *response);
+
+/**
+ * DeleteSubscriptions Service
+ * ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ * Invoked to delete one or more Subscriptions that belong to the Client's
+ * Session. */
+void Service_DeleteSubscriptions(UA_Server *server, UA_Session *session,
+ const UA_DeleteSubscriptionsRequest *request,
+ UA_DeleteSubscriptionsResponse *response);
+
+/**
+ * TransferSubscription Service
+ * ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ * Used to transfer a Subscription and its MonitoredItems from one Session to
+ * another. For example, a Client may need to reopen a Session and then transfer
+ * 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 */
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+
+/*********************************** amalgamated original file "/home/jvoe/open62541/build/src_generated/ua_namespace0.h" ***********************************/
+
+/* WARNING: This is a generated file.
+ * Any manual changes will be overwritten. */
+
+#ifndef UA_NAMESPACE0_H_
+#define UA_NAMESPACE0_H_
+
+
+#ifdef UA_NO_AMALGAMATION
+#else
+
+/* The following declarations are in the open62541.c file so here's needed when compiling nodesets externally */
+
+# ifndef UA_Nodestore_remove //this definition is needed to hide this code in the amalgamated .c file
+
+typedef UA_StatusCode (*UA_exchangeEncodeBuffer)(void *handle, UA_Byte **bufPos,
+ const UA_Byte **bufEnd);
+
+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;
+
+UA_StatusCode
+UA_decodeBinary(const UA_ByteString *src, size_t *offset, void *dst,
+ const UA_DataType *type, size_t customTypesSize,
+ const UA_DataType *customTypes) UA_FUNC_ATTR_WARN_UNUSED_RESULT;
+
+size_t
+UA_calcSizeBinary(void *p, const UA_DataType *type);
+
+const UA_DataType *
+UA_findDataTypeByBinary(const UA_NodeId *typeId);
+
+# endif // UA_Nodestore_remove
+
+#endif
+
+
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern UA_StatusCode ua_namespace0(UA_Server *server);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* UA_NAMESPACE0_H_ */
+
+/*********************************** amalgamated original file "/home/jvoe/open62541/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
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * Copyright 2015-2016 (c) Sten Grüner
+ * Copyright 2015-2017 (c) Julius Pfrommer, Fraunhofer IOSB
+ * Copyright 2015 (c) Oleksiy Vasylyev
+ * Copyright 2016-2017 (c) Florian Palm
+ * Copyright 2017 (c) Stefan Profanter, fortiss GmbH
+ * Copyright 2017 (c) Mark Giraud, Fraunhofer IOSB
+ */
+
+
+
+/**************************/
+/* Subscriptions Handling */
+/**************************/
+
+#ifdef UA_ENABLE_SUBSCRIPTIONS
+
+typedef struct UA_Client_NotificationsAckNumber {
+ LIST_ENTRY(UA_Client_NotificationsAckNumber) listEntry;
+ UA_SubscriptionAcknowledgement subAck;
+} UA_Client_NotificationsAckNumber;
+
+typedef struct UA_Client_MonitoredItem {
+ LIST_ENTRY(UA_Client_MonitoredItem) listEntry;
+ UA_UInt32 monitoredItemId;
+ UA_UInt32 clientHandle;
+ void *context;
+ UA_Client_DeleteMonitoredItemCallback deleteCallback;
+ union {
+ UA_Client_DataChangeNotificationCallback dataChangeCallback;
+ UA_Client_EventNotificationCallback eventCallback;
+ } handler;
+ UA_Boolean isEventMonitoredItem; /* Otherwise a DataChange MoniitoredItem */
+} UA_Client_MonitoredItem;
+
+typedef struct UA_Client_Subscription {
+ LIST_ENTRY(UA_Client_Subscription) listEntry;
+ UA_UInt32 subscriptionId;
+ void *context;
+ UA_Double publishingInterval;
+ UA_UInt32 maxKeepAliveCount;
+ UA_Client_StatusChangeNotificationCallback statusChangeCallback;
+ UA_Client_DeleteSubscriptionCallback deleteCallback;
+ UA_UInt32 sequenceNumber;
+ UA_DateTime lastActivity;
+ LIST_HEAD(UA_ListOfClientMonitoredItems, UA_Client_MonitoredItem) monitoredItems;
+} UA_Client_Subscription;
+
+void
+UA_Client_Subscriptions_clean(UA_Client *client);
+
+void
+UA_Client_MonitoredItem_remove(UA_Client *client, UA_Client_Subscription *sub,
+ UA_Client_MonitoredItem *mon);
+
+void
+UA_Client_Subscriptions_processPublishResponse(UA_Client *client,
+ UA_PublishRequest *request,
+ UA_PublishResponse *response);
+
+UA_StatusCode
+UA_Client_preparePublishRequest(UA_Client *client, UA_PublishRequest *request);
+
+UA_StatusCode
+UA_Client_Subscriptions_backgroundPublish(UA_Client *client);
+
+void
+UA_Client_Subscriptions_backgroundPublishInactivityCheck(UA_Client *client);
+
+#endif /* UA_ENABLE_SUBSCRIPTIONS */
+
+/**********/
+/* Client */
+/**********/
+
+typedef struct AsyncServiceCall {
+ LIST_ENTRY(AsyncServiceCall) pointers;
+ UA_UInt32 requestId;
+ UA_ClientAsyncServiceCallback callback;
+ const UA_DataType *responseType;
+ void *userdata;
+ UA_DateTime start;
+ UA_UInt32 timeout;
+} AsyncServiceCall;
+
+void UA_Client_AsyncService_cancel(UA_Client *client, AsyncServiceCall *ac,
+ UA_StatusCode statusCode);
+
+void UA_Client_AsyncService_removeAll(UA_Client *client, UA_StatusCode statusCode);
+
+typedef enum {
+ UA_CLIENTAUTHENTICATION_NONE,
+ UA_CLIENTAUTHENTICATION_USERNAME
+} UA_Client_Authentication;
+
+struct UA_Client {
+ /* State */
+ UA_ClientState state;
+
+ UA_ClientConfig config;
+
+ /* Connection */
+ UA_Connection connection;
+ UA_String endpointUrl;
+
+ /* SecureChannel */
+ UA_SecurityPolicy securityPolicy; /* TODO: Move supported policies to the config */
+ UA_SecureChannel channel;
+ UA_UInt32 requestId;
+ UA_DateTime nextChannelRenewal;
+
+ /* Authentication */
+ UA_Client_Authentication authenticationMethod;
+ UA_String username;
+ UA_String password;
+
+ /* Session */
+ UA_UserTokenPolicy token;
+ UA_NodeId authenticationToken;
+ UA_UInt32 requestHandle;
+
+ /* Async Service */
+ LIST_HEAD(ListOfAsyncServiceCall, AsyncServiceCall) asyncServiceCalls;
+
+ /* Subscriptions */
+#ifdef UA_ENABLE_SUBSCRIPTIONS
+ UA_UInt32 monitoredItemHandles;
+ LIST_HEAD(ListOfUnacknowledgedNotifications, UA_Client_NotificationsAckNumber) pendingNotificationsAcks;
+ LIST_HEAD(ListOfClientSubscriptionItems, UA_Client_Subscription) subscriptions;
+ UA_UInt16 currentlyOutStandingPublishRequests;
+#endif
+
+ /* Connectivity check */
+ UA_DateTime lastConnectivityCheck;
+ UA_Boolean pendingConnectivityCheck;
+};
+
+void
+setClientState(UA_Client *client, UA_ClientState state);
+
+UA_StatusCode
+UA_Client_connectInternal(UA_Client *client, const char *endpointUrl,
+ UA_Boolean endpointsHandshake, UA_Boolean createNewSession);
+
+UA_StatusCode
+UA_Client_getEndpointsInternal(UA_Client *client, size_t* endpointDescriptionsSize,
+ UA_EndpointDescription** endpointDescriptions);
+
+/* Receive and process messages until a synchronous message arrives or the
+ * timout finishes */
+UA_StatusCode
+receiveServiceResponse(UA_Client *client, void *response, const UA_DataType *responseType,
+ UA_DateTime maxDate, UA_UInt32 *synchronousRequestId);
+
+
+/*********************************** amalgamated original file "/home/jvoe/open62541/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
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * Copyright 2014-2017 (c) Julius Pfrommer, Fraunhofer IOSB
+ * Copyright 2014, 2016-2017 (c) Florian Palm
+ * Copyright 2014-2016 (c) Sten Grüner
+ * Copyright 2014 (c) Leon Urbas
+ * Copyright 2015 (c) Chris Iatrou
+ * Copyright 2015 (c) Markus Graube
+ * Copyright 2015 (c) Reza Ebrahimi
+ * Copyright 2015-2016 (c) Oleksiy Vasylyev
+ * Copyright 2017 (c) Stefan Profanter, fortiss GmbH
+ * Copyright 2016 (c) Lorenz Haas
+ */
+
+
+
+/* Datatype Handling
+ * -----------------
+ * This file contains handling functions for the builtin types and functions
+ * handling of structured types and arrays. These need type descriptions in a
+ * UA_DataType structure. The UA_DataType structures as well as all non-builtin
+ * datatypes are autogenerated. */
+
+/* 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};
+
+/* 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;
+
+ /* 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].typeId.identifier.numeric == typeId->identifier.numeric
+ && UA_TYPES[i].typeId.namespaceIndex == typeId->namespaceIndex)
+ 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];
+ }
+ }*/
+
+ return NULL;
+}
+
+/***************************/
+/* Random Number Generator */
+/***************************/
+
+//TODO is this safe for multithreading?
+static pcg32_random_t UA_rng = PCG32_INITIALIZER;
+
+void
+UA_random_seed(u64 seed) {
+ pcg32_srandom_r(&UA_rng, seed, (u64)UA_DateTime_now());
+}
+
+u32
+UA_UInt32_random(void) {
+ return (u32)pcg32_random_r(&UA_rng);
+}
+
+/*****************/
+/* Builtin Types */
+/*****************/
+
+static void deleteMembers_noInit(void *p, const UA_DataType *type);
+static UA_StatusCode copy_noInit(const void *src, void *dst, const UA_DataType *type);
+
+UA_String
+UA_String_fromChars(char const src[]) {
+ UA_String str;
+ str.length = strlen(src);
+ if(str.length > 0) {
+ str.data = (u8*)UA_malloc(str.length);
+ if(!str.data)
+ return UA_STRING_NULL;
+ memcpy(str.data, src, str.length);
+ } else {
+ str.data = (u8*)UA_EMPTY_ARRAY_SENTINEL;
+ }
+ return str;
+}
+
+UA_Boolean
+UA_String_equal(const UA_String *s1, const UA_String *s2) {
+ if(s1->length != s2->length)
+ return false;
+ i32 is = memcmp((char const*)s1->data,
+ (char const*)s2->data, s1->length);
+ return (is == 0) ? true : false;
+}
+
+static void
+String_deleteMembers(UA_String *s, const UA_DataType *_) {
+ UA_free((void*)((uintptr_t)s->data & ~(uintptr_t)UA_EMPTY_ARRAY_SENTINEL));
+}
+
+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);
+}
+
+/* DateTime */
+UA_DateTimeStruct
+UA_DateTime_toStruct(UA_DateTime t) {
+ /* Calculating the the milli-, micro- and nanoseconds */
+ UA_DateTimeStruct dateTimeStruct;
+ dateTimeStruct.nanoSec = (u16)((t % 10) * 100);
+ dateTimeStruct.microSec = (u16)((t % 10000) / 10);
+ dateTimeStruct.milliSec = (u16)((t % 10000000) / 10000);
+
+ /* Calculating the unix time with #include <time.h> */
+ long long secSinceUnixEpoch = (long long)
+ ((t - UA_DATETIME_UNIX_EPOCH) / 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;
+ dateTimeStruct.month = (u16)(ts.tm_mon + 1);
+ dateTimeStruct.year = (u16)(ts.tm_year + 1900);
+ return dateTimeStruct;
+}
+
+static void
+printNumber(u16 n, u8 *pos, size_t digits) {
+ for(size_t i = digits; i > 0; --i) {
+ pos[i-1] = (u8)((n % 10) + '0');
+ n = n / 10;
+ }
+}
+
+UA_String
+UA_DateTime_toString(UA_DateTime t) {
+ /* length of the string is 31 (plus \0 at the end) */
+ UA_String str = {31, (u8*)UA_malloc(32)};
+ if(!str.data)
+ return UA_STRING_NULL;
+ UA_DateTimeStruct tSt = UA_DateTime_toStruct(t);
+ printNumber(tSt.month, str.data, 2);
+ str.data[2] = '/';
+ printNumber(tSt.day, &str.data[3], 2);
+ str.data[5] = '/';
+ printNumber(tSt.year, &str.data[6], 4);
+ str.data[10] = ' ';
+ printNumber(tSt.hour, &str.data[11], 2);
+ str.data[13] = ':';
+ printNumber(tSt.min, &str.data[14], 2);
+ str.data[16] = ':';
+ printNumber(tSt.sec, &str.data[17], 2);
+ str.data[19] = '.';
+ printNumber(tSt.milliSec, &str.data[20], 3);
+ str.data[23] = '.';
+ printNumber(tSt.microSec, &str.data[24], 3);
+ str.data[27] = '.';
+ printNumber(tSt.nanoSec, &str.data[28], 3);
+ return str;
+}
+
+/* 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;
+}
+
+UA_Guid
+UA_Guid_random(void) {
+ UA_Guid result;
+ result.data1 = (u32)pcg32_random_r(&UA_rng);
+ u32 r = (u32)pcg32_random_r(&UA_rng);
+ result.data2 = (u16) r;
+ result.data3 = (u16) (r >> 16);
+ r = (u32)pcg32_random_r(&UA_rng);
+ result.data4[0] = (u8)r;
+ result.data4[1] = (u8)(r >> 4);
+ result.data4[2] = (u8)(r >> 8);
+ result.data4[3] = (u8)(r >> 12);
+ r = (u32)pcg32_random_r(&UA_rng);
+ result.data4[4] = (u8)r;
+ result.data4[5] = (u8)(r >> 4);
+ result.data4[6] = (u8)(r >> 8);
+ result.data4[7] = (u8)(r >> 12);
+ return result;
+}
+
+/* ByteString */
+UA_StatusCode
+UA_ByteString_allocBuffer(UA_ByteString *bs, size_t length) {
+ UA_ByteString_init(bs);
+ if(length == 0)
+ return UA_STATUSCODE_GOOD;
+ bs->data = (u8*)UA_malloc(length);
+ if(!bs->data)
+ return UA_STATUSCODE_BADOUTOFMEMORY;
+ bs->length = length;
+ return UA_STATUSCODE_GOOD;
+}
+
+/* NodeId */
+static void
+NodeId_deleteMembers(UA_NodeId *p, const UA_DataType *_) {
+ switch(p->identifierType) {
+ case UA_NODEIDTYPE_STRING:
+ case UA_NODEIDTYPE_BYTESTRING:
+ String_deleteMembers(&p->identifier.string, NULL);
+ break;
+ default: break;
+ }
+}
+
+static UA_StatusCode
+NodeId_copy(UA_NodeId const *src, UA_NodeId *dst, const UA_DataType *_) {
+ UA_StatusCode retval = UA_STATUSCODE_GOOD;
+ switch(src->identifierType) {
+ case UA_NODEIDTYPE_NUMERIC:
+ *dst = *src;
+ return UA_STATUSCODE_GOOD;
+ case UA_NODEIDTYPE_STRING:
+ retval |= UA_String_copy(&src->identifier.string,
+ &dst->identifier.string);
+ break;
+ case UA_NODEIDTYPE_GUID:
+ retval |= UA_Guid_copy(&src->identifier.guid, &dst->identifier.guid);
+ break;
+ case UA_NODEIDTYPE_BYTESTRING:
+ retval |= UA_ByteString_copy(&src->identifier.byteString,
+ &dst->identifier.byteString);
+ break;
+ default:
+ return UA_STATUSCODE_BADINTERNALERROR;
+ }
+ dst->namespaceIndex = src->namespaceIndex;
+ dst->identifierType = src->identifierType;
+ return retval;
+}
+
+UA_Boolean
+UA_NodeId_isNull(const UA_NodeId *p) {
+ if(p->namespaceIndex != 0)
+ return false;
+ switch(p->identifierType) {
+ 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_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;
+}
+
+UA_Boolean
+UA_NodeId_equal(const UA_NodeId *n1, const UA_NodeId *n2) {
+ if(n1 == NULL || n2 == NULL)
+ return false;
+ if(n1->namespaceIndex != n2->namespaceIndex ||
+ n1->identifierType!=n2->identifierType)
+ return false;
+ switch(n1->identifierType) {
+ case UA_NODEIDTYPE_NUMERIC:
+ return (n1->identifier.numeric == n2->identifier.numeric);
+ case UA_NODEIDTYPE_STRING:
+ return UA_String_equal(&n1->identifier.string,
+ &n2->identifier.string);
+ case UA_NODEIDTYPE_GUID:
+ return UA_Guid_equal(&n1->identifier.guid,
+ &n2->identifier.guid);
+ case UA_NODEIDTYPE_BYTESTRING:
+ return UA_ByteString_equal(&n1->identifier.byteString,
+ &n2->identifier.byteString);
+ }
+ return false;
+}
+
+UA_Boolean
+UA_ExpandedNodeId_equal(const UA_ExpandedNodeId *n1, const UA_ExpandedNodeId *n2) {
+ if(n1 == NULL || n2 == NULL)
+ return false;
+ if(n1->serverIndex != n2->serverIndex)
+ return false;
+ if(!UA_String_equal(&n1->namespaceUri, &n2->namespaceUri))
+ return false;
+ return UA_NodeId_equal(&n1->nodeId, &n2->nodeId);
+}
+
+/* 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
+static u32
+fnv32(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;
+}
+
+u32
+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 */
+ case UA_NODEIDTYPE_STRING:
+ case UA_NODEIDTYPE_BYTESTRING:
+ return fnv32(n->namespaceIndex, n->identifier.string.data, n->identifier.string.length);
+ case UA_NODEIDTYPE_GUID:
+ return fnv32(n->namespaceIndex, (const u8*)&n->identifier.guid, sizeof(UA_Guid));
+ }
+}
+
+/* ExpandedNodeId */
+static void
+ExpandedNodeId_deleteMembers(UA_ExpandedNodeId *p, const UA_DataType *_) {
+ NodeId_deleteMembers(&p->nodeId, _);
+ String_deleteMembers(&p->namespaceUri, NULL);
+}
+
+static UA_StatusCode
+ExpandedNodeId_copy(UA_ExpandedNodeId const *src, UA_ExpandedNodeId *dst,
+ const UA_DataType *_) {
+ UA_StatusCode retval = NodeId_copy(&src->nodeId, &dst->nodeId, NULL);
+ retval |= UA_String_copy(&src->namespaceUri, &dst->namespaceUri);
+ dst->serverIndex = src->serverIndex;
+ return retval;
+}
+
+/* ExtensionObject */
+static void
+ExtensionObject_deleteMembers(UA_ExtensionObject *p, const UA_DataType *_) {
+ switch(p->encoding) {
+ case UA_EXTENSIONOBJECT_ENCODED_NOBODY:
+ case UA_EXTENSIONOBJECT_ENCODED_BYTESTRING:
+ case UA_EXTENSIONOBJECT_ENCODED_XML:
+ NodeId_deleteMembers(&p->content.encoded.typeId, NULL);
+ String_deleteMembers(&p->content.encoded.body, NULL);
+ break;
+ case UA_EXTENSIONOBJECT_DECODED:
+ if(p->content.decoded.data)
+ UA_delete(p->content.decoded.data, p->content.decoded.type);
+ break;
+ default:
+ break;
+ }
+}
+
+static UA_StatusCode
+ExtensionObject_copy(UA_ExtensionObject const *src, UA_ExtensionObject *dst,
+ const UA_DataType *_) {
+ UA_StatusCode retval = UA_STATUSCODE_GOOD;
+ switch(src->encoding) {
+ case UA_EXTENSIONOBJECT_ENCODED_NOBODY:
+ case UA_EXTENSIONOBJECT_ENCODED_BYTESTRING:
+ case UA_EXTENSIONOBJECT_ENCODED_XML:
+ dst->encoding = src->encoding;
+ retval = NodeId_copy(&src->content.encoded.typeId,
+ &dst->content.encoded.typeId, NULL);
+ retval |= UA_ByteString_copy(&src->content.encoded.body,
+ &dst->content.encoded.body);
+ break;
+ case UA_EXTENSIONOBJECT_DECODED:
+ case UA_EXTENSIONOBJECT_DECODED_NODELETE:
+ if(!src->content.decoded.type || !src->content.decoded.data)
+ return UA_STATUSCODE_BADINTERNALERROR;
+ dst->encoding = UA_EXTENSIONOBJECT_DECODED;
+ dst->content.decoded.type = src->content.decoded.type;
+ retval = UA_Array_copy(src->content.decoded.data, 1,
+ &dst->content.decoded.data, src->content.decoded.type);
+ break;
+ default:
+ break;
+ }
+ return retval;
+}
+
+/* Variant */
+static void
+Variant_deletemembers(UA_Variant *p, const UA_DataType *_) {
+ if(p->storageType != UA_VARIANT_DATA)
+ return;
+ 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;
+ }
+ if((void*)p->arrayDimensions > UA_EMPTY_ARRAY_SENTINEL)
+ UA_free(p->arrayDimensions);
+}
+
+static UA_StatusCode
+Variant_copy(UA_Variant const *src, UA_Variant *dst, const UA_DataType *_) {
+ size_t length = src->arrayLength;
+ if(UA_Variant_isScalar(src))
+ length = 1;
+ UA_StatusCode retval = UA_Array_copy(src->data, length,
+ &dst->data, src->type);
+ if(retval != UA_STATUSCODE_GOOD)
+ return retval;
+ dst->arrayLength = src->arrayLength;
+ dst->type = src->type;
+ if(src->arrayDimensions) {
+ 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;
+ }
+ return UA_STATUSCODE_GOOD;
+}
+
+void
+UA_Variant_setScalar(UA_Variant *v, void * UA_RESTRICT p,
+ const UA_DataType *type) {
+ UA_Variant_init(v);
+ v->type = type;
+ v->arrayLength = 0;
+ v->data = p;
+}
+
+UA_StatusCode
+UA_Variant_setScalarCopy(UA_Variant *v, const void *p,
+ const UA_DataType *type) {
+ void *n = UA_malloc(type->memSize);
+ if(!n)
+ return UA_STATUSCODE_BADOUTOFMEMORY;
+ UA_StatusCode retval = UA_copy(p, n, type);
+ if(retval != UA_STATUSCODE_GOOD) {
+ UA_free(n);
+ //cppcheck-suppress memleak
+ return retval;
+ }
+ UA_Variant_setScalar(v, n, type);
+ //cppcheck-suppress memleak
+ return UA_STATUSCODE_GOOD;
+}
+
+void UA_Variant_setArray(UA_Variant *v, void * UA_RESTRICT array,
+ size_t arraySize, const UA_DataType *type) {
+ UA_Variant_init(v);
+ v->data = array;
+ v->arrayLength = arraySize;
+ v->type = type;
+}
+
+UA_StatusCode
+UA_Variant_setArrayCopy(UA_Variant *v, const void *array,
+ size_t arraySize, const UA_DataType *type) {
+ UA_Variant_init(v);
+ UA_StatusCode retval = UA_Array_copy(array, arraySize, &v->data, type);
+ if(retval != UA_STATUSCODE_GOOD)
+ return retval;
+ v->arrayLength = arraySize;
+ v->type = type;
+ 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 */
+static UA_StatusCode
+computeStrides(const UA_Variant *v, const UA_NumericRange range,
+ size_t *total, size_t *block, size_t *stride, size_t *first) {
+ /* 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;
+ }
+ UA_assert(dims_count > 0);
+
+ /* Test the integrity of the range and compute the max index used for every
+ * dimension. The standard says in Part 4, Section 7.22:
+ *
+ * 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;
+ UA_STACKARRAY(UA_UInt32, realmax, dims_count);
+ 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)
+ return UA_STATUSCODE_BADINDEXRANGEINVALID;
+ 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;
+ }
+
+ *total = count;
+
+ /* 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. */
+ *first = 0;
+ size_t running_dimssize = 1;
+ bool found_contiguous = false;
+ for(size_t k = dims_count; k > 0;) {
+ --k;
+ size_t dimrange = 1 + realmax[k] - range.dimensions[k].min;
+ if(!found_contiguous && dimrange != dims[k]) {
+ /* Found the maximum block that can be copied contiguously */
+ found_contiguous = true;
+ *block = running_dimssize * dimrange;
+ *stride = running_dimssize * dims[k];
+ }
+ *first += running_dimssize * range.dimensions[k].min;
+ running_dimssize *= dims[k];
+ }
+ return UA_STATUSCODE_GOOD;
+}
+
+/* Is the type string-like? */
+static bool
+isStringLike(const UA_DataType *type) {
+ if(type->membersSize == 1 && type->members[0].isArray &&
+ type->members[0].namespaceZero &&
+ type->members[0].memberTypeIndex == UA_TYPES_BYTE)
+ return true;
+ return false;
+}
+
+/* Returns the part of the string that lies within the rangedimension */
+static UA_StatusCode
+copySubString(const UA_String *src, UA_String *dst,
+ const UA_NumericRangeDimension *dim) {
+ if(dim->min > dim->max)
+ return UA_STATUSCODE_BADINDEXRANGEINVALID;
+ if(dim->min >= src->length)
+ return UA_STATUSCODE_BADINDEXRANGENODATA;
+
+ size_t length;
+ if(dim->max < src->length)
+ length = dim->max - dim->min + 1;
+ else
+ length = src->length - dim->min;
+
+ UA_StatusCode retval = UA_ByteString_allocBuffer(dst, length);
+ if(retval != UA_STATUSCODE_GOOD)
+ return retval;
+
+ memcpy(dst->data, &src->data[dim->min], length);
+ return UA_STATUSCODE_GOOD;
+}
+
+UA_StatusCode
+UA_Variant_copyRange(const UA_Variant *src, UA_Variant *dst,
+ const UA_NumericRange range) {
+ if(!src->type)
+ return UA_STATUSCODE_BADINVALIDARGUMENT;
+ bool isScalar = UA_Variant_isScalar(src);
+ bool stringLike = isStringLike(src->type);
+ UA_Variant arraySrc;
+
+ /* 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 */
+ if(isScalar) {
+ /* Replace scalar src with array of length 1 */
+ arraySrc = *src;
+ arraySrc.arrayLength = 1;
+ src = &arraySrc;
+ /* Deal with all range dimensions within the scalar */
+ thisrange.dimensions = &scalarThisDimension;
+ thisrange.dimensionsSize = 1;
+ nextrange = range;
+ } else {
+ /* Deal with as many range dimensions as possible right now */
+ size_t dims = src->arrayDimensionsSize;
+ if(dims == 0)
+ 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);
+ if(retval != UA_STATUSCODE_GOOD)
+ return retval;
+
+ /* Allocate the array */
+ UA_Variant_init(dst);
+ dst->data = UA_Array_new(count, src->type);
+ if(!dst->data)
+ return UA_STATUSCODE_BADOUTOFMEMORY;
+
+ /* Copy the range */
+ size_t block_count = count / block;
+ size_t elem_size = src->type->memSize;
+ uintptr_t nextdst = (uintptr_t)dst->data;
+ uintptr_t nextsrc = (uintptr_t)src->data + (elem_size * first);
+ if(nextrange.dimensionsSize == 0) {
+ /* no nextrange */
+ if(src->type->pointerFree) {
+ for(size_t i = 0; i < block_count; ++i) {
+ memcpy((void*)nextdst, (void*)nextsrc, elem_size * block);
+ nextdst += block * elem_size;
+ nextsrc += stride * elem_size;
+ }
+ } else {
+ for(size_t i = 0; i < block_count; ++i) {
+ for(size_t j = 0; j < block; ++j) {
+ retval = UA_copy((const void*)nextsrc,
+ (void*)nextdst, src->type);
+ nextdst += elem_size;
+ nextsrc += elem_size;
+ }
+ nextsrc += (stride - block) * elem_size;
+ }
+ }
+ } else {
+ /* nextrange can only be used for variants and stringlike with remaining
+ * range of dimension 1 */
+ if(src->type != &UA_TYPES[UA_TYPES_VARIANT]) {
+ if(!stringLike)
+ retval = UA_STATUSCODE_BADINDEXRANGENODATA;
+ if(nextrange.dimensionsSize != 1)
+ retval = UA_STATUSCODE_BADINDEXRANGENODATA;
+ }
+
+ /* Copy the content */
+ for(size_t i = 0; i < block_count; ++i) {
+ for(size_t j = 0; j < block && retval == UA_STATUSCODE_GOOD; ++j) {
+ if(stringLike)
+ retval = copySubString((const UA_String*)nextsrc,
+ (UA_String*)nextdst,
+ nextrange.dimensions);
+ else
+ retval = UA_Variant_copyRange((const UA_Variant*)nextsrc,
+ (UA_Variant*)nextdst,
+ nextrange);
+ nextdst += elem_size;
+ nextsrc += elem_size;
+ }
+ nextsrc += (stride - block) * elem_size;
+ }
+ }
+
+ /* Clean up if copying failed */
+ if(retval != UA_STATUSCODE_GOOD) {
+ UA_Array_delete(dst->data, count, src->type);
+ dst->data = NULL;
+ return retval;
+ }
+
+ /* Done if scalar */
+ dst->type = src->type;
+ if(isScalar)
+ return retval;
+
+ /* Copy array dimensions */
+ dst->arrayLength = count;
+ if(src->arrayDimensionsSize > 0) {
+ dst->arrayDimensions =
+ (u32*)UA_Array_new(thisrange.dimensionsSize, &UA_TYPES[UA_TYPES_UINT32]);
+ if(!dst->arrayDimensions) {
+ Variant_deletemembers(dst, NULL);
+ return UA_STATUSCODE_BADOUTOFMEMORY;
+ }
+ dst->arrayDimensionsSize = thisrange.dimensionsSize;
+ for(size_t k = 0; k < thisrange.dimensionsSize; ++k)
+ dst->arrayDimensions[k] =
+ thisrange.dimensions[k].max - thisrange.dimensions[k].min + 1;
+ }
+ return UA_STATUSCODE_GOOD;
+}
+
+/* TODO: Allow ranges to reach inside a scalars that are array-like, e.g.
+ * variant and strings. This is already possible for reading... */
+static UA_StatusCode
+Variant_setRange(UA_Variant *v, void *array, size_t arraySize,
+ const UA_NumericRange range, bool copy) {
+ /* Compute the strides */
+ size_t count, block, stride, first;
+ UA_StatusCode retval = computeStrides(v, range, &count,
+ &block, &stride, &first);
+ if(retval != UA_STATUSCODE_GOOD)
+ return retval;
+ if(count != arraySize)
+ return UA_STATUSCODE_BADINDEXRANGEINVALID;
+
+ /* Move/copy the elements */
+ size_t block_count = count / block;
+ size_t elem_size = v->type->memSize;
+ uintptr_t nextdst = (uintptr_t)v->data + (first * elem_size);
+ uintptr_t nextsrc = (uintptr_t)array;
+ if(v->type->pointerFree || !copy) {
+ for(size_t i = 0; i < block_count; ++i) {
+ memcpy((void*)nextdst, (void*)nextsrc, elem_size * block);
+ nextsrc += block * elem_size;
+ nextdst += stride * elem_size;
+ }
+ } else {
+ for(size_t i = 0; i < block_count; ++i) {
+ for(size_t j = 0; j < block; ++j) {
+ deleteMembers_noInit((void*)nextdst, v->type);
+ retval |= UA_copy((void*)nextsrc, (void*)nextdst, v->type);
+ nextdst += elem_size;
+ nextsrc += elem_size;
+ }
+ nextdst += (stride - block) * elem_size;
+ }
+ }
+
+ /* If members were moved, initialize original array to prevent reuse */
+ if(!copy && !v->type->pointerFree)
+ memset(array, 0, sizeof(elem_size)*arraySize);
+
+ return retval;
+}
+
+UA_StatusCode
+UA_Variant_setRange(UA_Variant *v, void * UA_RESTRICT array,
+ size_t arraySize, const UA_NumericRange range) {
+ return Variant_setRange(v, array, arraySize, range, false);
+}
+
+UA_StatusCode
+UA_Variant_setRangeCopy(UA_Variant *v, const void *array,
+ size_t arraySize, const UA_NumericRange range) {
+ return Variant_setRange(v, (void*)(uintptr_t)array,
+ arraySize, range, true);
+}
+
+/* LocalizedText */
+static void
+LocalizedText_deleteMembers(UA_LocalizedText *p, const UA_DataType *_) {
+ String_deleteMembers(&p->locale, NULL);
+ String_deleteMembers(&p->text, NULL);
+}
+
+static UA_StatusCode
+LocalizedText_copy(UA_LocalizedText const *src, UA_LocalizedText *dst,
+ const UA_DataType *_) {
+ UA_StatusCode retval = UA_String_copy(&src->locale, &dst->locale);
+ retval |= UA_String_copy(&src->text, &dst->text);
+ return retval;
+}
+
+/* DataValue */
+static void
+DataValue_deleteMembers(UA_DataValue *p, const UA_DataType *_) {
+ Variant_deletemembers(&p->value, NULL);
+}
+
+static UA_StatusCode
+DataValue_copy(UA_DataValue const *src, UA_DataValue *dst,
+ const UA_DataType *_) {
+ memcpy(dst, src, sizeof(UA_DataValue));
+ UA_Variant_init(&dst->value);
+ UA_StatusCode retval = Variant_copy(&src->value, &dst->value, NULL);
+ if(retval != UA_STATUSCODE_GOOD)
+ DataValue_deleteMembers(dst, NULL);
+ return retval;
+}
+
+/* DiagnosticInfo */
+static void
+DiagnosticInfo_deleteMembers(UA_DiagnosticInfo *p, const UA_DataType *_) {
+ String_deleteMembers(&p->additionalInfo, NULL);
+ if(p->hasInnerDiagnosticInfo && p->innerDiagnosticInfo) {
+ DiagnosticInfo_deleteMembers(p->innerDiagnosticInfo, NULL);
+ UA_free(p->innerDiagnosticInfo);
+ }
+}
+
+static UA_StatusCode
+DiagnosticInfo_copy(UA_DiagnosticInfo const *src, UA_DiagnosticInfo *dst,
+ const UA_DataType *_) {
+ memcpy(dst, src, sizeof(UA_DiagnosticInfo));
+ UA_String_init(&dst->additionalInfo);
+ dst->innerDiagnosticInfo = NULL;
+ UA_StatusCode retval = UA_STATUSCODE_GOOD;
+ 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) {
+ retval |= DiagnosticInfo_copy(src->innerDiagnosticInfo,
+ dst->innerDiagnosticInfo, NULL);
+ dst->hasInnerDiagnosticInfo = true;
+ } else {
+ dst->hasInnerDiagnosticInfo = false;
+ retval |= UA_STATUSCODE_BADOUTOFMEMORY;
+ }
+ }
+ return retval;
+}
+
+/********************/
+/* Structured Types */
+/********************/
+
+void *
+UA_new(const UA_DataType *type) {
+ void *p = UA_calloc(1, type->memSize);
+ return p;
+}
+
+static UA_StatusCode
+copyByte(const u8 *src, u8 *dst, const UA_DataType *_) {
+ *dst = *src;
+ return UA_STATUSCODE_GOOD;
+}
+
+static UA_StatusCode
+copy2Byte(const u16 *src, u16 *dst, const UA_DataType *_) {
+ *dst = *src;
+ return UA_STATUSCODE_GOOD;
+}
+
+static UA_StatusCode
+copy4Byte(const u32 *src, u32 *dst, const UA_DataType *_) {
+ *dst = *src;
+ return UA_STATUSCODE_GOOD;
+}
+
+static UA_StatusCode
+copy8Byte(const u64 *src, u64 *dst, const UA_DataType *_) {
+ *dst = *src;
+ return UA_STATUSCODE_GOOD;
+}
+
+static UA_StatusCode
+copyGuid(const UA_Guid *src, UA_Guid *dst, const UA_DataType *_) {
+ *dst = *src;
+ return UA_STATUSCODE_GOOD;
+}
+
+typedef UA_StatusCode
+(*UA_copySignature)(const void *src, void *dst, const UA_DataType *type);
+
+static const UA_copySignature copyJumpTable[UA_BUILTIN_TYPES_COUNT + 1] = {
+ (UA_copySignature)copyByte, // Boolean
+ (UA_copySignature)copyByte, // SByte
+ (UA_copySignature)copyByte, // Byte
+ (UA_copySignature)copy2Byte, // Int16
+ (UA_copySignature)copy2Byte, // UInt16
+ (UA_copySignature)copy4Byte, // Int32
+ (UA_copySignature)copy4Byte, // UInt32
+ (UA_copySignature)copy8Byte, // Int64
+ (UA_copySignature)copy8Byte, // UInt64
+ (UA_copySignature)copy4Byte, // Float
+ (UA_copySignature)copy8Byte, // Double
+ (UA_copySignature)copy_noInit, // String
+ (UA_copySignature)copy8Byte, // DateTime
+ (UA_copySignature)copyGuid, // Guid
+ (UA_copySignature)copy_noInit, // ByteString
+ (UA_copySignature)copy_noInit, // XmlElement
+ (UA_copySignature)NodeId_copy,
+ (UA_copySignature)ExpandedNodeId_copy,
+ (UA_copySignature)copy4Byte, // StatusCode
+ (UA_copySignature)copy_noInit, // QualifiedName
+ (UA_copySignature)LocalizedText_copy, // LocalizedText
+ (UA_copySignature)ExtensionObject_copy,
+ (UA_copySignature)DataValue_copy,
+ (UA_copySignature)Variant_copy,
+ (UA_copySignature)DiagnosticInfo_copy,
+ (UA_copySignature)copy_noInit // all others
+};
+
+static UA_StatusCode
+copy_noInit(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;
+ u8 membersSize = type->membersSize;
+ for(size_t i = 0; i < membersSize; ++i) {
+ const UA_DataTypeMember *m= &type->members[i];
+ const UA_DataType *typelists[2] = { UA_TYPES, &type[-type->typeIndex] };
+ const UA_DataType *mt = &typelists[!m->namespaceZero][m->memberTypeIndex];
+ if(!m->isArray) {
+ ptrs += m->padding;
+ ptrd += m->padding;
+ size_t fi = mt->builtin ? mt->typeIndex : UA_BUILTIN_TYPES_COUNT;
+ retval |= copyJumpTable[fi]((const void*)ptrs, (void*)ptrd, mt);
+ ptrs += mt->memSize;
+ ptrd += mt->memSize;
+ } else {
+ ptrs += m->padding;
+ ptrd += m->padding;
+ 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;
+ ptrs += sizeof(void*);
+ ptrd += sizeof(void*);
+ }
+ }
+ return retval;
+}
+
+UA_StatusCode
+UA_copy(const void *src, void *dst, const UA_DataType *type) {
+ memset(dst, 0, type->memSize); /* init */
+ UA_StatusCode retval = copy_noInit(src, dst, type);
+ if(retval != UA_STATUSCODE_GOOD)
+ UA_deleteMembers(dst, type);
+ return retval;
+}
+
+static void nopDeleteMembers(void *p, const UA_DataType *type) { }
+
+typedef void (*UA_deleteMembersSignature)(void *p, const UA_DataType *type);
+
+static const
+UA_deleteMembersSignature deleteMembersJumpTable[UA_BUILTIN_TYPES_COUNT + 1] = {
+ (UA_deleteMembersSignature)nopDeleteMembers, // Boolean
+ (UA_deleteMembersSignature)nopDeleteMembers, // SByte
+ (UA_deleteMembersSignature)nopDeleteMembers, // Byte
+ (UA_deleteMembersSignature)nopDeleteMembers, // Int16
+ (UA_deleteMembersSignature)nopDeleteMembers, // UInt16
+ (UA_deleteMembersSignature)nopDeleteMembers, // Int32
+ (UA_deleteMembersSignature)nopDeleteMembers, // UInt32
+ (UA_deleteMembersSignature)nopDeleteMembers, // Int64
+ (UA_deleteMembersSignature)nopDeleteMembers, // UInt64
+ (UA_deleteMembersSignature)nopDeleteMembers, // Float
+ (UA_deleteMembersSignature)nopDeleteMembers, // Double
+ (UA_deleteMembersSignature)String_deleteMembers, // String
+ (UA_deleteMembersSignature)nopDeleteMembers, // DateTime
+ (UA_deleteMembersSignature)nopDeleteMembers, // Guid
+ (UA_deleteMembersSignature)String_deleteMembers, // ByteString
+ (UA_deleteMembersSignature)String_deleteMembers, // XmlElement
+ (UA_deleteMembersSignature)NodeId_deleteMembers,
+ (UA_deleteMembersSignature)ExpandedNodeId_deleteMembers, // ExpandedNodeId
+ (UA_deleteMembersSignature)nopDeleteMembers, // StatusCode
+ (UA_deleteMembersSignature)deleteMembers_noInit, // QualifiedName
+ (UA_deleteMembersSignature)LocalizedText_deleteMembers, // LocalizedText
+ (UA_deleteMembersSignature)ExtensionObject_deleteMembers,
+ (UA_deleteMembersSignature)DataValue_deleteMembers,
+ (UA_deleteMembersSignature)Variant_deletemembers,
+ (UA_deleteMembersSignature)DiagnosticInfo_deleteMembers,
+ (UA_deleteMembersSignature)deleteMembers_noInit,
+};
+
+static void
+deleteMembers_noInit(void *p, const UA_DataType *type) {
+ uintptr_t ptr = (uintptr_t)p;
+ u8 membersSize = type->membersSize;
+ for(size_t i = 0; i < membersSize; ++i) {
+ const UA_DataTypeMember *m= &type->members[i];
+ const UA_DataType *typelists[2] = { UA_TYPES, &type[-type->typeIndex] };
+ const UA_DataType *mt = &typelists[!m->namespaceZero][m->memberTypeIndex];
+ if(!m->isArray) {
+ ptr += m->padding;
+ size_t fi = mt->builtin ? mt->typeIndex : UA_BUILTIN_TYPES_COUNT;
+ deleteMembersJumpTable[fi]((void*)ptr, mt);
+ ptr += mt->memSize;
+ } else {
+ ptr += m->padding;
+ size_t length = *(size_t*)ptr;
+ ptr += sizeof(size_t);
+ UA_Array_delete(*(void**)ptr, length, mt);
+ ptr += sizeof(void*);
+ }
+ }
+}
+
+void
+UA_deleteMembers(void *p, const UA_DataType *type) {
+ deleteMembers_noInit(p, type);
+ memset(p, 0, type->memSize); /* init */
+}
+
+void
+UA_delete(void *p, const UA_DataType *type) {
+ deleteMembers_noInit(p, type);
+ UA_free(p);
+}
+
+/******************/
+/* Array Handling */
+/******************/
+
+void *
+UA_Array_new(size_t size, const UA_DataType *type) {
+ if(size > UA_INT32_MAX)
+ return NULL;
+ if(size == 0)
+ return UA_EMPTY_ARRAY_SENTINEL;
+ return UA_calloc(size, type->memSize);
+}
+
+UA_StatusCode
+UA_Array_copy(const void *src, size_t size,
+ void **dst, const UA_DataType *type) {
+ if(size == 0) {
+ if(src == NULL)
+ *dst = NULL;
+ else
+ *dst= UA_EMPTY_ARRAY_SENTINEL;
+ return UA_STATUSCODE_GOOD;
+ }
+
+ if(!type)
+ return UA_STATUSCODE_BADINTERNALERROR;
+
+ /* calloc, so we don't have to check retval in every iteration of copying */
+ *dst = UA_calloc(size, type->memSize);
+ if(!*dst)
+ return UA_STATUSCODE_BADOUTOFMEMORY;
+
+ if(type->pointerFree) {
+ memcpy(*dst, src, type->memSize * size);
+ return UA_STATUSCODE_GOOD;
+ }
+
+ uintptr_t ptrs = (uintptr_t)src;
+ uintptr_t ptrd = (uintptr_t)*dst;
+ UA_StatusCode retval = UA_STATUSCODE_GOOD;
+ for(size_t i = 0; i < size; ++i) {
+ retval |= UA_copy((void*)ptrs, (void*)ptrd, type);
+ ptrs += type->memSize;
+ ptrd += type->memSize;
+ }
+ if(retval != UA_STATUSCODE_GOOD) {
+ UA_Array_delete(*dst, size, type);
+ *dst = NULL;
+ }
+ return retval;
+}
+
+void
+UA_Array_delete(void *p, size_t size, const UA_DataType *type) {
+ if(!type->pointerFree) {
+ uintptr_t ptr = (uintptr_t)p;
+ for(size_t i = 0; i < size; ++i) {
+ UA_deleteMembers((void*)ptr, type);
+ ptr += type->memSize;
+ }
+ }
+ UA_free((void*)((uintptr_t)p & ~(uintptr_t)UA_EMPTY_ARRAY_SENTINEL));
+}
+
+UA_Boolean
+isDataTypeNumeric(const UA_DataType *type) {
+ // All data types ids between UA_TYPES_BOOLEAN and UA_TYPES_DOUBLE are numeric
+ for (int i = UA_TYPES_BOOLEAN; i <= UA_TYPES_DOUBLE; ++i)
+ if (&UA_TYPES[i] == type)
+ return true;
+ return false;
+}
+
+/*********************************** amalgamated original file "/home/jvoe/open62541/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
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * Copyright 2014-2018 (c) Julius Pfrommer, Fraunhofer IOSB
+ * Copyright 2014-2017 (c) Florian Palm
+ * Copyright 2014-2016 (c) Sten Grüner
+ * Copyright 2014 (c) Leon Urbas
+ * Copyright 2015 (c) LEvertz
+ * Copyright 2015 (c) Chris Iatrou
+ * Copyright 2015-2016 (c) Oleksiy Vasylyev
+ * Copyright 2016-2017 (c) Stefan Profanter, fortiss GmbH
+ * Copyright 2016 (c) Lorenz Haas
+ * Copyright 2017 (c) Mark Giraud, Fraunhofer IOSB
+ * Copyright 2017 (c) Henrik Norrman
+ */
+
+
+/**
+ * Type Encoding and Decoding
+ * --------------------------
+ * The following methods contain encoding and decoding functions for the builtin
+ * 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 . */
+
+#define UA_ENCODING_MAX_RECURSION 20
+
+typedef struct {
+ /* Pointers to the current position and the last position in the buffer */
+ u8 *pos;
+ const u8 *end;
+
+ u16 depth; /* How often did we en-/decoding recurse? */
+
+ size_t customTypesArraySize;
+ const UA_DataType *customTypesArray;
+
+ UA_exchangeEncodeBuffer exchangeBufferCallback;
+ void *exchangeBufferCallbackHandle;
+} Ctx;
+
+typedef status (*encodeBinarySignature)(const void *UA_RESTRICT src, const UA_DataType *type,
+ Ctx *UA_RESTRICT ctx);
+typedef status (*decodeBinarySignature)(void *UA_RESTRICT dst, const UA_DataType *type,
+ Ctx *UA_RESTRICT ctx);
+typedef size_t (*calcSizeBinarySignature)(const void *UA_RESTRICT p, const UA_DataType *contenttype);
+
+#define ENCODE_BINARY(TYPE) static status \
+ TYPE##_encodeBinary(const UA_##TYPE *UA_RESTRICT src, const UA_DataType *type, Ctx *UA_RESTRICT ctx)
+#define DECODE_BINARY(TYPE) static status \
+ TYPE##_decodeBinary(UA_##TYPE *UA_RESTRICT dst, const UA_DataType *type, Ctx *UA_RESTRICT ctx)
+#define CALCSIZE_BINARY(TYPE) static size_t \
+ TYPE##_calcSizeBinary(const UA_##TYPE *UA_RESTRICT src, const UA_DataType *_)
+#define ENCODE_DIRECT(SRC, TYPE) TYPE##_encodeBinary((const UA_##TYPE*)SRC, NULL, ctx)
+#define DECODE_DIRECT(DST, TYPE) TYPE##_decodeBinary((UA_##TYPE*)DST, NULL, ctx)
+
+/* Jumptables for de-/encoding and computing the buffer length. The methods in
+ * the decoding jumptable do not all clean up their allocated memory when an
+ * error occurs. So a final _deleteMembers needs to be called before returning
+ * to the user. */
+extern const encodeBinarySignature encodeBinaryJumpTable[UA_BUILTIN_TYPES_COUNT + 1];
+extern const decodeBinarySignature decodeBinaryJumpTable[UA_BUILTIN_TYPES_COUNT + 1];
+extern const calcSizeBinarySignature calcSizeBinaryJumpTable[UA_BUILTIN_TYPES_COUNT + 1];
+static status encodeBinaryInternal(const void *src, const UA_DataType *type, Ctx *ctx);
+static status decodeBinaryInternal(void *dst, const UA_DataType *type, Ctx *ctx);
+
+/**
+ * Chunking
+ * ^^^^^^^^
+ * Breaking a message 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.
+ *
+ * In encodeBinaryInternal and Array_encodeBinary, we store a pointer to the
+ * last "good position" in the buffer. If we reach the end of the buffer, the
+ * encoding until that point is sent out. Afterwards the "good position" pointer
+ * is no longer valid. In order to prevent reuse, no method must return
+ * UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED after having called exchangeBuffer().
+ * This needs to be ensured for the following methods:
+ *
+ * encodeBinaryInternal
+ * Array_encodeBinary
+ * NodeId_encodeBinary
+ * ExpandedNodeId_encodeBinary
+ * LocalizedText_encodeBinary
+ * ExtensionObject_encodeBinary
+ * Variant_encodeBinary
+ * DataValue_encodeBinary
+ * DiagnosticInfo_encodeBinary */
+
+/* Send the current chunk and replace the buffer */
+static status exchangeBuffer(Ctx *ctx) {
+ if(!ctx->exchangeBufferCallback)
+ return UA_STATUSCODE_BADENCODINGERROR;
+ return ctx->exchangeBufferCallback(ctx->exchangeBufferCallbackHandle, &ctx->pos, &ctx->end);
+}
+
+/* If encoding fails, exchange the buffer and try again. It is assumed that the
+ * following encoding never fails on a fresh buffer. This is true for numerical
+ * types. */
+static status
+encodeWithExchangeBuffer(const void *ptr, encodeBinarySignature encodeFunc, Ctx *ctx) {
+ status ret = encodeFunc(ptr, NULL, ctx);
+ if(ret == UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED) {
+ ret = exchangeBuffer(ctx);
+ if(ret != UA_STATUSCODE_GOOD)
+ return ret;
+ ret = encodeFunc(ptr, NULL, ctx);
+ }
+ return ret;
+}
+
+#define ENCODE_WITHEXCHANGE(VAR, TYPE) \
+ encodeWithExchangeBuffer((const void*)VAR, (encodeBinarySignature)TYPE##_encodeBinary, ctx)
+
+/*****************/
+/* Integer Types */
+/*****************/
+
+#if !UA_BINARY_OVERLAYABLE_INTEGER
+
+#pragma message "Integer endianness could not be detected to be little endian. Use slow generic encoding."
+
+/* These en/decoding functions are only used when the architecture isn't little-endian. */
+static void
+UA_encode16(const u16 v, u8 buf[2]) {
+ buf[0] = (u8)v;
+ buf[1] = (u8)(v >> 8);
+}
+
+static void
+UA_decode16(const u8 buf[2], u16 *v) {
+ *v = (u16)((u16)buf[0] + (((u16)buf[1]) << 8));
+}
+
+static void
+UA_encode32(const u32 v, u8 buf[4]) {
+ buf[0] = (u8)v;
+ buf[1] = (u8)(v >> 8);
+ buf[2] = (u8)(v >> 16);
+ buf[3] = (u8)(v >> 24);
+}
+
+static void
+UA_decode32(const u8 buf[4], u32 *v) {
+ *v = (u32)((u32)buf[0] + (((u32)buf[1]) << 8) +
+ (((u32)buf[2]) << 16) + (((u32)buf[3]) << 24));
+}
+
+static void
+UA_encode64(const u64 v, u8 buf[8]) {
+ buf[0] = (u8)v;
+ buf[1] = (u8)(v >> 8);
+ buf[2] = (u8)(v >> 16);
+ buf[3] = (u8)(v >> 24);
+ buf[4] = (u8)(v >> 32);
+ buf[5] = (u8)(v >> 40);
+ buf[6] = (u8)(v >> 48);
+ buf[7] = (u8)(v >> 56);
+}
+
+static void
+UA_decode64(const u8 buf[8], u64 *v) {
+ *v = (u64)((u64)buf[0] + (((u64)buf[1]) << 8) +
+ (((u64)buf[2]) << 16) + (((u64)buf[3]) << 24) +
+ (((u64)buf[4]) << 32) + (((u64)buf[5]) << 40) +
+ (((u64)buf[6]) << 48) + (((u64)buf[7]) << 56));
+}
+
+#endif /* !UA_BINARY_OVERLAYABLE_INTEGER */
+
+/* Boolean */
+ENCODE_BINARY(Boolean) {
+ if(ctx->pos + sizeof(bool) > ctx->end)
+ return UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED;
+ *ctx->pos = *(const u8*)src;
+ ++ctx->pos;
+ return UA_STATUSCODE_GOOD;
+}
+
+DECODE_BINARY(Boolean) {
+ if(ctx->pos + sizeof(bool) > ctx->end)
+ return UA_STATUSCODE_BADDECODINGERROR;
+ *dst = (*ctx->pos > 0) ? true : false;
+ ++ctx->pos;
+ return UA_STATUSCODE_GOOD;
+}
+
+/* Byte */
+ENCODE_BINARY(Byte) {
+ if(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;
+ *dst = *ctx->pos;
+ ++ctx->pos;
+ return UA_STATUSCODE_GOOD;
+}
+
+/* UInt16 */
+ENCODE_BINARY(UInt16) {
+ if(ctx->pos + sizeof(u16) > ctx->end)
+ return UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED;
+#if UA_BINARY_OVERLAYABLE_INTEGER
+ memcpy(ctx->pos, src, sizeof(u16));
+#else
+ UA_encode16(*src, ctx->pos);
+#endif
+ ctx->pos += 2;
+ return UA_STATUSCODE_GOOD;
+}
+
+DECODE_BINARY(UInt16) {
+ if(ctx->pos + sizeof(u16) > ctx->end)
+ return UA_STATUSCODE_BADDECODINGERROR;
+#if UA_BINARY_OVERLAYABLE_INTEGER
+ memcpy(dst, ctx->pos, sizeof(u16));
+#else
+ UA_decode16(ctx->pos, dst);
+#endif
+ ctx->pos += 2;
+ return UA_STATUSCODE_GOOD;
+}
+
+/* UInt32 */
+ENCODE_BINARY(UInt32) {
+ if(ctx->pos + sizeof(u32) > ctx->end)
+ return UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED;
+#if UA_BINARY_OVERLAYABLE_INTEGER
+ memcpy(ctx->pos, src, sizeof(u32));
+#else
+ UA_encode32(*src, ctx->pos);
+#endif
+ ctx->pos += 4;
+ return UA_STATUSCODE_GOOD;
+}
+
+DECODE_BINARY(UInt32) {
+ if(ctx->pos + sizeof(u32) > ctx->end)
+ return UA_STATUSCODE_BADDECODINGERROR;
+#if UA_BINARY_OVERLAYABLE_INTEGER
+ memcpy(dst, ctx->pos, sizeof(u32));
+#else
+ UA_decode32(ctx->pos, dst);
+#endif
+ ctx->pos += 4;
+ return UA_STATUSCODE_GOOD;
+}
+
+/* UInt64 */
+ENCODE_BINARY(UInt64) {
+ if(ctx->pos + sizeof(u64) > ctx->end)
+ return UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED;
+#if UA_BINARY_OVERLAYABLE_INTEGER
+ memcpy(ctx->pos, src, sizeof(u64));
+#else
+ UA_encode64(*src, ctx->pos);
+#endif
+ ctx->pos += 8;
+ return UA_STATUSCODE_GOOD;
+}
+
+DECODE_BINARY(UInt64) {
+ if(ctx->pos + sizeof(u64) > ctx->end)
+ return UA_STATUSCODE_BADDECODINGERROR;
+#if UA_BINARY_OVERLAYABLE_INTEGER
+ memcpy(dst, ctx->pos, sizeof(u64));
+#else
+ UA_decode64(ctx->pos, dst);
+#endif
+ ctx->pos += 8;
+ return UA_STATUSCODE_GOOD;
+}
+
+/************************/
+/* Floating Point Types */
+/************************/
+
+#if UA_BINARY_OVERLAYABLE_FLOAT
+# define Float_encodeBinary UInt32_encodeBinary
+# define Float_decodeBinary UInt32_decodeBinary
+# define Double_encodeBinary UInt64_encodeBinary
+# define Double_decodeBinary UInt64_decodeBinary
+#else
+
+#include <math.h>
+
+#pragma message "No native IEEE 754 format detected. Use slow generic encoding."
+
+/* Handling of IEEE754 floating point values was taken from Beej's Guide to
+ * Network Programming (http://beej.us/guide/bgnet/) and enhanced to cover the
+ * edge cases +/-0, +/-inf and nan. */
+static uint64_t
+pack754(long double f, unsigned bits, unsigned expbits) {
+ unsigned significandbits = bits - expbits - 1;
+ long double fnorm;
+ long long sign;
+ if(f < 0) { sign = 1; fnorm = -f; }
+ else { sign = 0; fnorm = f; }
+ int shift = 0;
+ while(fnorm >= 2.0) { fnorm /= 2.0; ++shift; }
+ while(fnorm < 1.0) { fnorm *= 2.0; --shift; }
+ fnorm = fnorm - 1.0;
+ long long significand = (long long)(fnorm * ((float)(1LL<<significandbits) + 0.5f));
+ long long exponent = shift + ((1<<(expbits-1)) - 1);
+ return (uint64_t)((sign<<(bits-1)) | (exponent<<(bits-expbits-1)) | significand);
+}
+
+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 += 1.0f;
+ unsigned bias = (unsigned)(1<<(expbits-1)) - 1;
+ long long shift = (long long)((i>>significandbits) & (uint64_t)((1LL<<expbits)-1)) - bias;
+ while(shift > 0) { result *= 2.0; --shift; }
+ while(shift < 0) { result /= 2.0; ++shift; }
+ result *= ((i>>(bits-1))&1)? -1.0: 1.0;
+ return result;
+}
+
+/* Float */
+#define FLOAT_NAN 0xffc00000
+#define FLOAT_INF 0x7f800000
+#define FLOAT_NEG_INF 0xff800000
+#define FLOAT_NEG_ZERO 0x80000000
+
+ENCODE_BINARY(Float) {
+ UA_Float f = *src;
+ u32 encoded;
+ /* cppcheck-suppress duplicateExpression */
+ if(f != f) encoded = FLOAT_NAN;
+ else if(f == 0.0f) encoded = signbit(f) ? FLOAT_NEG_ZERO : 0;
+ else if(f/f != f/f) encoded = f > 0 ? FLOAT_INF : FLOAT_NEG_INF;
+ else encoded = (u32)pack754(f, 32, 8);
+ return ENCODE_DIRECT(&encoded, UInt32);
+}
+
+DECODE_BINARY(Float) {
+ u32 decoded;
+ status ret = DECODE_DIRECT(&decoded, UInt32);
+ if(ret != UA_STATUSCODE_GOOD)
+ return ret;
+ if(decoded == 0) *dst = 0.0f;
+ else if(decoded == FLOAT_NEG_ZERO) *dst = -0.0f;
+ else if(decoded == FLOAT_INF) *dst = INFINITY;
+ else if(decoded == FLOAT_NEG_INF) *dst = -INFINITY;
+ else if((decoded >= 0x7f800001 && decoded <= 0x7fffffff) ||
+ (decoded >= 0xff800001)) *dst = NAN;
+ else *dst = (UA_Float)unpack754(decoded, 32, 8);
+ return UA_STATUSCODE_GOOD;
+}
+
+/* Double */
+#define DOUBLE_NAN 0xfff8000000000000L
+#define DOUBLE_INF 0x7ff0000000000000L
+#define DOUBLE_NEG_INF 0xfff0000000000000L
+#define DOUBLE_NEG_ZERO 0x8000000000000000L
+
+ENCODE_BINARY(Double) {
+ UA_Double d = *src;
+ u64 encoded;
+ /* cppcheck-suppress duplicateExpression */
+ if(d != d) encoded = DOUBLE_NAN;
+ else if(d == 0.0) encoded = signbit(d) ? DOUBLE_NEG_ZERO : 0;
+ else if(d/d != d/d) encoded = d > 0 ? DOUBLE_INF : DOUBLE_NEG_INF;
+ else encoded = pack754(d, 64, 11);
+ return ENCODE_DIRECT(&encoded, UInt64);
+}
+
+DECODE_BINARY(Double) {
+ u64 decoded;
+ status ret = DECODE_DIRECT(&decoded, UInt64);
+ if(ret != UA_STATUSCODE_GOOD)
+ return ret;
+ if(decoded == 0) *dst = 0.0;
+ else if(decoded == DOUBLE_NEG_ZERO) *dst = -0.0;
+ else if(decoded == DOUBLE_INF) *dst = INFINITY;
+ else if(decoded == DOUBLE_NEG_INF) *dst = -INFINITY;
+ else if((decoded >= 0x7ff0000000000001L && decoded <= 0x7fffffffffffffffL) ||
+ (decoded >= 0xfff0000000000001L)) *dst = NAN;
+ else *dst = (UA_Double)unpack754(decoded, 64, 11);
+ return UA_STATUSCODE_GOOD;
+}
+
+#endif
+
+/******************/
+/* Array Handling */
+/******************/
+
+static status
+Array_encodeBinaryOverlayable(uintptr_t ptr, size_t length, size_t elementMemSize, Ctx *ctx) {
+ /* Store the number of already encoded elements */
+ size_t finished = 0;
+
+ /* Loop as long as more elements remain than fit into the chunk */
+ while(ctx->end < ctx->pos + (elementMemSize * (length-finished))) {
+ size_t possible = ((uintptr_t)ctx->end - (uintptr_t)ctx->pos) / (sizeof(u8) * elementMemSize);
+ size_t possibleMem = possible * elementMemSize;
+ memcpy(ctx->pos, (void*)ptr, possibleMem);
+ ctx->pos += possibleMem;
+ ptr += possibleMem;
+ finished += possible;
+ status ret = exchangeBuffer(ctx);
+ if(ret != UA_STATUSCODE_GOOD)
+ return ret;
+ }
+
+ /* Encode the remaining elements */
+ memcpy(ctx->pos, (void*)ptr, elementMemSize * (length-finished));
+ ctx->pos += elementMemSize * (length-finished);
+ return UA_STATUSCODE_GOOD;
+}
+
+static status
+Array_encodeBinaryComplex(uintptr_t ptr, size_t length, const UA_DataType *type, Ctx *ctx) {
+ /* Get the encoding function for the data type. The jumptable at
+ * UA_BUILTIN_TYPES_COUNT points to the generic UA_encodeBinary method */
+ size_t encode_index = type->builtin ? type->typeIndex : UA_BUILTIN_TYPES_COUNT;
+ encodeBinarySignature encodeType = encodeBinaryJumpTable[encode_index];
+
+ /* Encode every element */
+ for(size_t i = 0; i < length; ++i) {
+ u8 *oldpos = ctx->pos;
+ status ret = encodeType((const void*)ptr, type, ctx);
+ ptr += type->memSize;
+ /* Encoding failed, switch to the next chunk when possible */
+ if(ret != UA_STATUSCODE_GOOD) {
+ if(ret == UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED) {
+ ctx->pos = oldpos; /* Set buffer position to the end of the last encoded element */
+ ret = exchangeBuffer(ctx);
+ ptr -= type->memSize; /* Undo to retry encoding the ith element */
+ --i;
+ }
+ UA_assert(ret != UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED);
+ if(ret != UA_STATUSCODE_GOOD)
+ return ret; /* Unrecoverable fail */
+ }
+ }
+ return UA_STATUSCODE_GOOD;
+}
+
+static status
+Array_encodeBinary(const void *src, size_t length, const UA_DataType *type, Ctx *ctx) {
+ /* Check and convert the array length to int32 */
+ i32 signed_length = -1;
+ if(length > UA_INT32_MAX)
+ return UA_STATUSCODE_BADINTERNALERROR;
+ if(length > 0)
+ signed_length = (i32)length;
+ else if(src == UA_EMPTY_ARRAY_SENTINEL)
+ signed_length = 0;
+
+ /* Encode the array length */
+ status ret = ENCODE_WITHEXCHANGE(&signed_length, UInt32);
+
+ /* Quit early? */
+ if(ret != UA_STATUSCODE_GOOD || length == 0)
+ return ret;
+
+ /* Encode the content */
+ if(!type->overlayable)
+ return Array_encodeBinaryComplex((uintptr_t)src, length, type, ctx);
+ return Array_encodeBinaryOverlayable((uintptr_t)src, length, type->memSize, ctx);
+}
+
+static status
+Array_decodeBinary(void *UA_RESTRICT *UA_RESTRICT dst, size_t *out_length,
+ const UA_DataType *type, Ctx *ctx) {
+ /* Decode the length */
+ i32 signed_length;
+ status ret = DECODE_DIRECT(&signed_length, UInt32); /* Int32 */
+ if(ret != UA_STATUSCODE_GOOD)
+ return ret;
+
+ /* Return early for empty arrays */
+ if(signed_length <= 0) {
+ *out_length = 0;
+ if(signed_length < 0)
+ *dst = NULL;
+ else
+ *dst = UA_EMPTY_ARRAY_SENTINEL;
+ return UA_STATUSCODE_GOOD;
+ }
+
+ /* Filter out arrays that can obviously not be decoded, because the message
+ * 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;
+
+ /* Allocate memory */
+ *dst = UA_calloc(length, type->memSize);
+ if(!*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;
+ }
+ memcpy(*dst, ctx->pos, type->memSize * length);
+ ctx->pos += type->memSize * length;
+ } else {
+ /* Decode array members */
+ uintptr_t ptr = (uintptr_t)*dst;
+ size_t decode_index = type->builtin ? type->typeIndex : UA_BUILTIN_TYPES_COUNT;
+ for(size_t i = 0; i < length; ++i) {
+ ret = decodeBinaryJumpTable[decode_index]((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;
+ }
+ ptr += type->memSize;
+ }
+ }
+ *out_length = length;
+ return UA_STATUSCODE_GOOD;
+}
+
+/*****************/
+/* Builtin Types */
+/*****************/
+
+ENCODE_BINARY(String) {
+ return Array_encodeBinary(src->data, src->length, &UA_TYPES[UA_TYPES_BYTE], ctx);
+}
+
+DECODE_BINARY(String) {
+ return Array_decodeBinary((void**)&dst->data, &dst->length, &UA_TYPES[UA_TYPES_BYTE], ctx);
+}
+
+/* Guid */
+ENCODE_BINARY(Guid) {
+ status ret = UA_STATUSCODE_GOOD;
+ 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;
+ memcpy(ctx->pos, src->data4, 8*sizeof(u8));
+ ctx->pos += 8;
+ return ret;
+}
+
+DECODE_BINARY(Guid) {
+ status ret = UA_STATUSCODE_GOOD;
+ 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;
+ memcpy(dst->data4, ctx->pos, 8*sizeof(u8));
+ ctx->pos += 8;
+ return ret;
+}
+
+/* NodeId */
+#define UA_NODEIDTYPE_NUMERIC_TWOBYTE 0
+#define UA_NODEIDTYPE_NUMERIC_FOURBYTE 1
+#define UA_NODEIDTYPE_NUMERIC_COMPLETE 2
+
+#define UA_EXPANDEDNODEID_SERVERINDEX_FLAG 0x40
+#define UA_EXPANDEDNODEID_NAMESPACEURI_FLAG 0x80
+
+/* For ExpandedNodeId, we prefill the encoding mask. We can return
+ * UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED before encoding the string, as the
+ * buffer is not replaced. */
+static status
+NodeId_encodeBinaryWithEncodingMask(UA_NodeId const *src, u8 encoding, Ctx *ctx) {
+ status ret = UA_STATUSCODE_GOOD;
+ switch(src->identifierType) {
+ case UA_NODEIDTYPE_NUMERIC:
+ if(src->identifier.numeric > UA_UINT16_MAX || src->namespaceIndex > UA_BYTE_MAX) {
+ encoding |= UA_NODEIDTYPE_NUMERIC_COMPLETE;
+ ret |= ENCODE_DIRECT(&encoding, Byte);
+ ret |= ENCODE_DIRECT(&src->namespaceIndex, UInt16);
+ ret |= ENCODE_DIRECT(&src->identifier.numeric, UInt32);
+ } else if(src->identifier.numeric > UA_BYTE_MAX || src->namespaceIndex > 0) {
+ encoding |= UA_NODEIDTYPE_NUMERIC_FOURBYTE;
+ ret |= ENCODE_DIRECT(&encoding, Byte);
+ u8 nsindex = (u8)src->namespaceIndex;
+ ret |= ENCODE_DIRECT(&nsindex, Byte);
+ u16 identifier16 = (u16)src->identifier.numeric;
+ ret |= ENCODE_DIRECT(&identifier16, UInt16);
+ } else {
+ encoding |= UA_NODEIDTYPE_NUMERIC_TWOBYTE;
+ ret |= ENCODE_DIRECT(&encoding, Byte);
+ u8 identifier8 = (u8)src->identifier.numeric;
+ ret |= ENCODE_DIRECT(&identifier8, Byte);
+ }
+ break;
+ case UA_NODEIDTYPE_STRING:
+ encoding |= UA_NODEIDTYPE_STRING;
+ ret |= ENCODE_DIRECT(&encoding, Byte);
+ ret |= ENCODE_DIRECT(&src->namespaceIndex, UInt16);
+ if(ret != UA_STATUSCODE_GOOD)
+ return ret;
+ ret = ENCODE_DIRECT(&src->identifier.string, String);
+ break;
+ case UA_NODEIDTYPE_GUID:
+ encoding |= UA_NODEIDTYPE_GUID;
+ ret |= ENCODE_DIRECT(&encoding, Byte);
+ ret |= ENCODE_DIRECT(&src->namespaceIndex, UInt16);
+ ret |= ENCODE_DIRECT(&src->identifier.guid, Guid);
+ break;
+ case UA_NODEIDTYPE_BYTESTRING:
+ encoding |= UA_NODEIDTYPE_BYTESTRING;
+ ret |= ENCODE_DIRECT(&encoding, Byte);
+ ret |= ENCODE_DIRECT(&src->namespaceIndex, UInt16);
+ if(ret != UA_STATUSCODE_GOOD)
+ return ret;
+ ret = ENCODE_DIRECT(&src->identifier.byteString, String); /* ByteString */
+ break;
+ default:
+ return UA_STATUSCODE_BADINTERNALERROR;
+ }
+ return ret;
+}
+
+ENCODE_BINARY(NodeId) {
+ return NodeId_encodeBinaryWithEncodingMask(src, 0, ctx);
+}
+
+DECODE_BINARY(NodeId) {
+ u8 dstByte = 0, encodingByte = 0;
+ u16 dstUInt16 = 0;
+
+ /* Decode the encoding bitfield */
+ status ret = DECODE_DIRECT(&encodingByte, Byte);
+ if(ret != UA_STATUSCODE_GOOD)
+ return ret;
+
+ /* Filter out the bits used only for ExpandedNodeIds */
+ encodingByte &= (u8)~(UA_EXPANDEDNODEID_SERVERINDEX_FLAG |
+ UA_EXPANDEDNODEID_NAMESPACEURI_FLAG);
+
+ /* Decode the namespace and identifier */
+ switch(encodingByte) {
+ case UA_NODEIDTYPE_NUMERIC_TWOBYTE:
+ dst->identifierType = UA_NODEIDTYPE_NUMERIC;
+ ret = DECODE_DIRECT(&dstByte, Byte);
+ dst->identifier.numeric = dstByte;
+ dst->namespaceIndex = 0;
+ break;
+ case UA_NODEIDTYPE_NUMERIC_FOURBYTE:
+ dst->identifierType = UA_NODEIDTYPE_NUMERIC;
+ ret |= DECODE_DIRECT(&dstByte, Byte);
+ dst->namespaceIndex = dstByte;
+ ret |= DECODE_DIRECT(&dstUInt16, UInt16);
+ dst->identifier.numeric = dstUInt16;
+ break;
+ case UA_NODEIDTYPE_NUMERIC_COMPLETE:
+ dst->identifierType = UA_NODEIDTYPE_NUMERIC;
+ ret |= DECODE_DIRECT(&dst->namespaceIndex, UInt16);
+ ret |= DECODE_DIRECT(&dst->identifier.numeric, UInt32);
+ break;
+ case UA_NODEIDTYPE_STRING:
+ dst->identifierType = UA_NODEIDTYPE_STRING;
+ ret |= DECODE_DIRECT(&dst->namespaceIndex, UInt16);
+ ret |= DECODE_DIRECT(&dst->identifier.string, String);
+ break;
+ case UA_NODEIDTYPE_GUID:
+ dst->identifierType = UA_NODEIDTYPE_GUID;
+ ret |= DECODE_DIRECT(&dst->namespaceIndex, UInt16);
+ ret |= DECODE_DIRECT(&dst->identifier.guid, Guid);
+ break;
+ case UA_NODEIDTYPE_BYTESTRING:
+ dst->identifierType = UA_NODEIDTYPE_BYTESTRING;
+ ret |= DECODE_DIRECT(&dst->namespaceIndex, UInt16);
+ ret |= DECODE_DIRECT(&dst->identifier.byteString, String); /* ByteString */
+ break;
+ default:
+ ret |= UA_STATUSCODE_BADINTERNALERROR;
+ break;
+ }
+ return ret;
+}
+
+/* ExpandedNodeId */
+ENCODE_BINARY(ExpandedNodeId) {
+ /* Set up the encoding mask */
+ u8 encoding = 0;
+ if((void*)src->namespaceUri.data > UA_EMPTY_ARRAY_SENTINEL)
+ encoding |= UA_EXPANDEDNODEID_NAMESPACEURI_FLAG;
+ if(src->serverIndex > 0)
+ encoding |= UA_EXPANDEDNODEID_SERVERINDEX_FLAG;
+
+ /* Encode the NodeId */
+ status ret = NodeId_encodeBinaryWithEncodingMask(&src->nodeId, encoding, ctx);
+ if(ret != UA_STATUSCODE_GOOD)
+ return ret;
+
+ /* Encode the namespace. Do not return
+ * UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED afterwards. */
+ 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;
+ }
+
+ /* Encode the serverIndex */
+ if(src->serverIndex > 0)
+ ret = ENCODE_WITHEXCHANGE(&src->serverIndex, UInt32);
+ UA_assert(ret != UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED);
+ return ret;
+}
+
+DECODE_BINARY(ExpandedNodeId) {
+ /* Decode the encoding mask */
+ if(ctx->pos >= ctx->end)
+ return UA_STATUSCODE_BADDECODINGERROR;
+ u8 encoding = *ctx->pos;
+
+ /* Decode the NodeId */
+ status ret = DECODE_DIRECT(&dst->nodeId, NodeId);
+
+ /* Decode the NamespaceUri */
+ if(encoding & UA_EXPANDEDNODEID_NAMESPACEURI_FLAG) {
+ dst->nodeId.namespaceIndex = 0;
+ ret |= DECODE_DIRECT(&dst->namespaceUri, String);
+ }
+
+ /* Decode the ServerIndex */
+ if(encoding & UA_EXPANDEDNODEID_SERVERINDEX_FLAG)
+ ret |= DECODE_DIRECT(&dst->serverIndex, UInt32);
+ return ret;
+}
+
+/* LocalizedText */
+#define UA_LOCALIZEDTEXT_ENCODINGMASKTYPE_LOCALE 0x01
+#define UA_LOCALIZEDTEXT_ENCODINGMASKTYPE_TEXT 0x02
+
+ENCODE_BINARY(LocalizedText) {
+ /* Set up the encoding mask */
+ u8 encoding = 0;
+ if(src->locale.data)
+ encoding |= UA_LOCALIZEDTEXT_ENCODINGMASKTYPE_LOCALE;
+ if(src->text.data)
+ encoding |= UA_LOCALIZEDTEXT_ENCODINGMASKTYPE_TEXT;
+
+ /* Encode the encoding byte */
+ status ret = ENCODE_DIRECT(&encoding, Byte);
+ if(ret != UA_STATUSCODE_GOOD)
+ return ret;
+
+ /* Encode the strings */
+ if(encoding & UA_LOCALIZEDTEXT_ENCODINGMASKTYPE_LOCALE)
+ ret |= ENCODE_DIRECT(&src->locale, String);
+ if(encoding & UA_LOCALIZEDTEXT_ENCODINGMASKTYPE_TEXT)
+ ret |= ENCODE_DIRECT(&src->text, String);
+ UA_assert(ret != UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED);
+ return ret;
+}
+
+DECODE_BINARY(LocalizedText) {
+ /* Decode the encoding mask */
+ u8 encoding = 0;
+ status ret = DECODE_DIRECT(&encoding, Byte);
+
+ /* Decode the content */
+ if(encoding & UA_LOCALIZEDTEXT_ENCODINGMASKTYPE_LOCALE)
+ ret |= DECODE_DIRECT(&dst->locale, String);
+ if(encoding & UA_LOCALIZEDTEXT_ENCODINGMASKTYPE_TEXT)
+ ret |= DECODE_DIRECT(&dst->text, String);
+ return ret;
+}
+
+/* The binary encoding has a different nodeid from the data type. So it is not
+ * 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];
+ }
+
+ /* When other namespace look in custom types, too */
+ if(typeId->namespaceIndex != 0) {
+ for(size_t i = 0; i < ctx->customTypesArraySize; ++i) {
+ if(ctx->customTypesArray[i].binaryEncodingId == typeId->identifier.numeric &&
+ ctx->customTypesArray[i].typeId.namespaceIndex == typeId->namespaceIndex)
+ return &ctx->customTypesArray[i];
+ }
+ }
+
+ return NULL;
+}
+
+const UA_DataType *
+UA_findDataTypeByBinary(const UA_NodeId *typeId) {
+ Ctx ctx;
+ ctx.customTypesArraySize = 0;
+ ctx.customTypesArray = NULL;
+ return UA_findDataTypeByBinaryInternal(typeId, &ctx);
+}
+
+/* ExtensionObject */
+ENCODE_BINARY(ExtensionObject) {
+ u8 encoding = (u8)src->encoding;
+
+ /* No content or already encoded content. Do not return
+ * UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED after encoding the NodeId. */
+ if(encoding <= UA_EXTENSIONOBJECT_ENCODED_XML) {
+ status ret = ENCODE_DIRECT(&src->content.encoded.typeId, NodeId);
+ if(ret != UA_STATUSCODE_GOOD)
+ return ret;
+ ret = ENCODE_WITHEXCHANGE(&encoding, Byte);
+ if(ret != UA_STATUSCODE_GOOD)
+ 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 */
+ break;
+ default:
+ ret = UA_STATUSCODE_BADINTERNALERROR;
+ }
+ return ret;
+ }
+
+ /* Cannot encode with no data or no type description */
+ 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);
+
+ /* Write the encoding byte */
+ encoding = UA_EXTENSIONOBJECT_ENCODED_BYTESTRING;
+ ret |= ENCODE_DIRECT(&encoding, Byte);
+
+ /* Compute the content length */
+ const UA_DataType *contentType = src->content.decoded.type;
+ size_t len = UA_calcSizeBinary(src->content.decoded.data, contentType);
+
+ /* Encode the content length */
+ if(len > UA_INT32_MAX)
+ return UA_STATUSCODE_BADENCODINGERROR;
+ i32 signed_len = (i32)len;
+ ret |= ENCODE_DIRECT(&signed_len, UInt32); /* Int32 */
+
+ /* Return early upon failures (no buffer exchange until here) */
+ if(ret != UA_STATUSCODE_GOOD)
+ return ret;
+
+ /* Encode the content */
+ return encodeBinaryInternal(src->content.decoded.data, contentType, ctx);
+}
+
+static status
+ExtensionObject_decodeBinaryContent(UA_ExtensionObject *dst, const UA_NodeId *typeId, Ctx *ctx) {
+ /* Lookup the datatype */
+ const UA_DataType *type = UA_findDataTypeByBinaryInternal(typeId, ctx);
+
+ /* Unknown type, just take the binary content */
+ if(!type) {
+ dst->encoding = UA_EXTENSIONOBJECT_ENCODED_BYTESTRING;
+ UA_NodeId_copy(typeId, &dst->content.encoded.typeId);
+ return DECODE_DIRECT(&dst->content.encoded.body, String); /* ByteString */
+ }
+
+ /* Allocate memory */
+ dst->content.decoded.data = UA_new(type);
+ if(!dst->content.decoded.data)
+ return UA_STATUSCODE_BADOUTOFMEMORY;
+
+ /* Jump over the length field (TODO: check if the decoded length matches) */
+ ctx->pos += 4;
+
+ /* Decode */
+ dst->encoding = UA_EXTENSIONOBJECT_DECODED;
+ dst->content.decoded.type = type;
+ size_t decode_index = type->builtin ? type->typeIndex : UA_BUILTIN_TYPES_COUNT;
+ return decodeBinaryJumpTable[decode_index](dst->content.decoded.data, type, ctx);
+}
+
+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_init(&binTypeId);
+ status ret = UA_STATUSCODE_GOOD;
+ ret |= DECODE_DIRECT(&binTypeId, NodeId);
+ ret |= DECODE_DIRECT(&encoding, Byte);
+ if(ret != UA_STATUSCODE_GOOD) {
+ UA_NodeId_deleteMembers(&binTypeId);
+ return ret;
+ }
+
+ if(encoding == UA_EXTENSIONOBJECT_ENCODED_BYTESTRING) {
+ ret = ExtensionObject_decodeBinaryContent(dst, &binTypeId, ctx);
+ UA_NodeId_deleteMembers(&binTypeId);
+ } else if(encoding == UA_EXTENSIONOBJECT_ENCODED_NOBODY) {
+ dst->encoding = (UA_ExtensionObjectEncoding)encoding;
+ dst->content.encoded.typeId = binTypeId; /* move to dst */
+ dst->content.encoded.body = UA_BYTESTRING_NULL;
+ } else if(encoding == UA_EXTENSIONOBJECT_ENCODED_XML) {
+ 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_deleteMembers(&dst->content.encoded.typeId);
+ } else {
+ UA_NodeId_deleteMembers(&binTypeId);
+ ret = UA_STATUSCODE_BADDECODINGERROR;
+ }
+
+ return ret;
+}
+
+/* Variant */
+
+/* Never returns UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED */
+static status
+Variant_encodeBinaryWrapExtensionObject(const UA_Variant *src, const bool isArray, Ctx *ctx) {
+ /* Default to 1 for a scalar. */
+ size_t length = 1;
+
+ /* Encode the array length if required */
+ status ret = UA_STATUSCODE_GOOD;
+ if(isArray) {
+ if(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;
+ }
+
+ /* Set up the ExtensionObject */
+ UA_ExtensionObject eo;
+ UA_ExtensionObject_init(&eo);
+ eo.encoding = UA_EXTENSIONOBJECT_DECODED;
+ eo.content.decoded.type = src->type;
+ const u16 memSize = src->type->memSize;
+ uintptr_t ptr = (uintptr_t)src->data;
+
+ /* Iterate over the array */
+ for(size_t i = 0; i < length && ret == UA_STATUSCODE_GOOD; ++i) {
+ eo.content.decoded.data = (void*)ptr;
+ ret = encodeBinaryInternal(&eo, &UA_TYPES[UA_TYPES_EXTENSIONOBJECT], ctx);
+ ptr += memSize;
+ }
+ return ret;
+}
+
+enum UA_VARIANT_ENCODINGMASKTYPE {
+ UA_VARIANT_ENCODINGMASKTYPE_TYPEID_MASK = 0x3F, /* bits 0:5 */
+ UA_VARIANT_ENCODINGMASKTYPE_DIMENSIONS = (0x01 << 6), /* bit 6 */
+ UA_VARIANT_ENCODINGMASKTYPE_ARRAY = (0x01 << 7) /* bit 7 */
+};
+
+
+
+ENCODE_BINARY(Variant) {
+ /* Quit early for the empty variant */
+ u8 encoding = 0;
+ if(!src->type)
+ return ENCODE_DIRECT(&encoding, Byte);
+
+ /* Set the content type in the encoding mask */
+ const bool isBuiltin = src->type->builtin;
+ const bool isAlias = src->type->membersSize == 1
+ && UA_TYPES[src->type->members[0].memberTypeIndex].builtin;
+ if(isBuiltin)
+ encoding |= UA_VARIANT_ENCODINGMASKTYPE_TYPEID_MASK & (u8)(src->type->typeIndex + 1);
+ else if(isAlias)
+ encoding |= UA_VARIANT_ENCODINGMASKTYPE_TYPEID_MASK & (u8)(src->type->members[0].memberTypeIndex + 1);
+ else
+ encoding |= UA_VARIANT_ENCODINGMASKTYPE_TYPEID_MASK & (u8)(UA_TYPES_EXTENSIONOBJECT + 1);
+
+ /* Set the array type in the encoding mask */
+ const bool isArray = src->arrayLength > 0 || src->data <= UA_EMPTY_ARRAY_SENTINEL;
+ const bool hasDimensions = isArray && src->arrayDimensionsSize > 0;
+ if(isArray) {
+ encoding |= UA_VARIANT_ENCODINGMASKTYPE_ARRAY;
+ if(hasDimensions)
+ encoding |= UA_VARIANT_ENCODINGMASKTYPE_DIMENSIONS;
+ }
+
+ /* Encode the encoding byte */
+ status ret = ENCODE_DIRECT(&encoding, Byte);
+ if(ret != UA_STATUSCODE_GOOD)
+ return ret;
+
+ /* Encode the content */
+ if(!isBuiltin && !isAlias)
+ ret = Variant_encodeBinaryWrapExtensionObject(src, isArray, ctx);
+ else if(!isArray)
+ ret = encodeBinaryInternal(src->data, src->type, ctx);
+ else
+ ret = Array_encodeBinary(src->data, src->arrayLength, src->type, ctx);
+
+ /* Encode the array dimensions */
+ if(hasDimensions && ret == UA_STATUSCODE_GOOD)
+ ret = Array_encodeBinary(src->arrayDimensions, src->arrayDimensionsSize,
+ &UA_TYPES[UA_TYPES_INT32], ctx);
+ return ret;
+}
+
+static status
+Variant_decodeBinaryUnwrapExtensionObject(UA_Variant *dst, Ctx *ctx) {
+ /* Save the position in the ByteString. If unwrapping is not possible, start
+ * from here to decode a normal ExtensionObject. */
+ u8 *old_pos = ctx->pos;
+
+ /* Decode the DataType */
+ UA_NodeId typeId;
+ UA_NodeId_init(&typeId);
+ status ret = DECODE_DIRECT(&typeId, NodeId);
+ if(ret != UA_STATUSCODE_GOOD)
+ return ret;
+
+ /* Decode the EncodingByte */
+ u8 encoding;
+ ret = DECODE_DIRECT(&encoding, Byte);
+ if(ret != UA_STATUSCODE_GOOD) {
+ UA_NodeId_deleteMembers(&typeId);
+ return ret;
+ }
+
+ /* Search for the datatype. Default to ExtensionObject. */
+ if(encoding == UA_EXTENSIONOBJECT_ENCODED_BYTESTRING &&
+ (dst->type = UA_findDataTypeByBinaryInternal(&typeId, ctx)) != NULL) {
+ /* Jump over the length field (TODO: check if length matches) */
+ ctx->pos += 4;
+ } else {
+ /* Reset and decode as ExtensionObject */
+ dst->type = &UA_TYPES[UA_TYPES_EXTENSIONOBJECT];
+ ctx->pos = old_pos;
+ UA_NodeId_deleteMembers(&typeId);
+ }
+
+ /* Allocate memory */
+ dst->data = UA_new(dst->type);
+ if(!dst->data)
+ return UA_STATUSCODE_BADOUTOFMEMORY;
+
+ /* Decode the content */
+ size_t decode_index = dst->type->builtin ? dst->type->typeIndex : UA_BUILTIN_TYPES_COUNT;
+ return decodeBinaryJumpTable[decode_index](dst->data, dst->type, ctx);
+}
+
+/* The resulting variant always has the storagetype UA_VARIANT_DATA. */
+DECODE_BINARY(Variant) {
+ /* Decode the encoding byte */
+ u8 encodingByte;
+ status ret = DECODE_DIRECT(&encodingByte, Byte);
+ if(ret != UA_STATUSCODE_GOOD)
+ return ret;
+
+ /* Return early for an empty variant (was already _inited) */
+ if(encodingByte == 0)
+ return UA_STATUSCODE_GOOD;
+
+ /* Does the variant contain an array? */
+ const bool isArray = (encodingByte & UA_VARIANT_ENCODINGMASKTYPE_ARRAY) > 0;
+
+ /* Get the datatype of the content. The type must be a builtin data type.
+ * All not-builtin types are wrapped in an ExtensionObject. */
+ size_t typeIndex = (size_t)((encodingByte & UA_VARIANT_ENCODINGMASKTYPE_TYPEID_MASK) - 1);
+ if(typeIndex > UA_TYPES_DIAGNOSTICINFO)
+ return UA_STATUSCODE_BADDECODINGERROR;
+
+ /* A variant cannot contain a variant. But it can contain an array of
+ * variants */
+ if(typeIndex == UA_TYPES_VARIANT && !isArray)
+ return UA_STATUSCODE_BADDECODINGERROR;
+
+ /* Check the recursion limit */
+ if(ctx->depth > UA_ENCODING_MAX_RECURSION)
+ return UA_STATUSCODE_BADENCODINGERROR;
+ ctx->depth++;
+
+ /* Decode the content */
+ dst->type = &UA_TYPES[typeIndex];
+ if(isArray) {
+ ret = Array_decodeBinary(&dst->data, &dst->arrayLength, dst->type, ctx);
+ } else if(typeIndex != UA_TYPES_EXTENSIONOBJECT) {
+ dst->data = UA_new(dst->type);
+ if(!dst->data)
+ return UA_STATUSCODE_BADOUTOFMEMORY;
+ ret = decodeBinaryJumpTable[typeIndex](dst->data, dst->type, ctx);
+ } else {
+ ret = Variant_decodeBinaryUnwrapExtensionObject(dst, ctx);
+ }
+
+ /* Decode array dimensions */
+ if(isArray && (encodingByte & UA_VARIANT_ENCODINGMASKTYPE_DIMENSIONS) > 0)
+ ret |= Array_decodeBinary((void**)&dst->arrayDimensions, &dst->arrayDimensionsSize,
+ &UA_TYPES[UA_TYPES_INT32], ctx);
+
+ ctx->depth--;
+ return ret;
+}
+
+/* DataValue */
+ENCODE_BINARY(DataValue) {
+ /* Set up the encoding mask */
+ u8 encodingMask = (u8)
+ (((u8)src->hasValue) |
+ ((u8)src->hasStatus << 1) |
+ ((u8)src->hasSourceTimestamp << 2) |
+ ((u8)src->hasServerTimestamp << 3) |
+ ((u8)src->hasSourcePicoseconds << 4) |
+ ((u8)src->hasServerPicoseconds << 5));
+
+ /* Encode the encoding byte */
+ status ret = ENCODE_DIRECT(&encodingMask, Byte);
+ if(ret != UA_STATUSCODE_GOOD)
+ return ret;
+
+ /* Encode the variant. Afterwards, do not return
+ * UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED, as the buffer might have been
+ * exchanged during encoding of the variant. */
+ if(src->hasValue) {
+ ret = ENCODE_DIRECT(&src->value, Variant);
+ if(ret != UA_STATUSCODE_GOOD)
+ return ret;
+ }
+
+ if(src->hasStatus)
+ ret |= ENCODE_WITHEXCHANGE(&src->status, UInt32);
+ if(src->hasSourceTimestamp)
+ ret |= ENCODE_WITHEXCHANGE(&src->sourceTimestamp, UInt64);
+ if(src->hasSourcePicoseconds)
+ ret |= ENCODE_WITHEXCHANGE(&src->sourcePicoseconds, UInt16);
+ if(src->hasServerTimestamp)
+ ret |= ENCODE_WITHEXCHANGE(&src->serverTimestamp, UInt64);
+ if(src->hasServerPicoseconds)
+ ret |= ENCODE_WITHEXCHANGE(&src->serverPicoseconds, UInt16);
+ UA_assert(ret != UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED);
+ return ret;
+}
+
+#define MAX_PICO_SECONDS 9999
+
+DECODE_BINARY(DataValue) {
+ /* Decode the encoding mask */
+ u8 encodingMask;
+ status ret = DECODE_DIRECT(&encodingMask, Byte);
+ if(ret != UA_STATUSCODE_GOOD)
+ return ret;
+
+ /* Check the recursion limit */
+ if(ctx->depth > UA_ENCODING_MAX_RECURSION)
+ return UA_STATUSCODE_BADENCODINGERROR;
+ ctx->depth++;
+
+
+ /* Decode the content */
+ if(encodingMask & 0x01) {
+ dst->hasValue = true;
+ ret |= DECODE_DIRECT(&dst->value, Variant);
+ }
+ if(encodingMask & 0x02) {
+ dst->hasStatus = true;
+ ret |= DECODE_DIRECT(&dst->status, UInt32); /* StatusCode */
+ }
+ if(encodingMask & 0x04) {
+ dst->hasSourceTimestamp = true;
+ ret |= DECODE_DIRECT(&dst->sourceTimestamp, UInt64); /* DateTime */
+ }
+ if(encodingMask & 0x10) {
+ dst->hasSourcePicoseconds = true;
+ ret |= DECODE_DIRECT(&dst->sourcePicoseconds, UInt16);
+ if(dst->sourcePicoseconds > MAX_PICO_SECONDS)
+ dst->sourcePicoseconds = MAX_PICO_SECONDS;
+ }
+ if(encodingMask & 0x08) {
+ dst->hasServerTimestamp = true;
+ ret |= DECODE_DIRECT(&dst->serverTimestamp, UInt64); /* DateTime */
+ }
+ if(encodingMask & 0x20) {
+ dst->hasServerPicoseconds = true;
+ ret |= DECODE_DIRECT(&dst->serverPicoseconds, UInt16);
+ if(dst->serverPicoseconds > MAX_PICO_SECONDS)
+ dst->serverPicoseconds = MAX_PICO_SECONDS;
+ }
+
+ ctx->depth--;
+
+ return ret;
+}
+
+/* DiagnosticInfo */
+ENCODE_BINARY(DiagnosticInfo) {
+ /* Set up the encoding mask */
+ u8 encodingMask = (u8)
+ ((u8)src->hasSymbolicId | ((u8)src->hasNamespaceUri << 1) |
+ ((u8)src->hasLocalizedText << 2) | ((u8)src->hasLocale << 3) |
+ ((u8)src->hasAdditionalInfo << 4) | ((u8)src->hasInnerDiagnosticInfo << 5));
+
+ /* Encode the numeric content */
+ status ret = ENCODE_DIRECT(&encodingMask, Byte);
+ if(src->hasSymbolicId)
+ ret |= ENCODE_DIRECT(&src->symbolicId, UInt32); /* Int32 */
+ if(src->hasNamespaceUri)
+ ret |= ENCODE_DIRECT(&src->namespaceUri, UInt32); /* Int32 */
+ if(src->hasLocalizedText)
+ ret |= ENCODE_DIRECT(&src->localizedText, UInt32); /* Int32 */
+ if(src->hasLocale)
+ ret |= ENCODE_DIRECT(&src->locale, UInt32); /* Int32 */
+ if(ret != UA_STATUSCODE_GOOD)
+ return ret;
+
+ /* Encode the additional info */
+ if(src->hasAdditionalInfo) {
+ ret = ENCODE_DIRECT(&src->additionalInfo, String);
+ if(ret != UA_STATUSCODE_GOOD)
+ return ret;
+ }
+
+ /* From here on, do not return UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED, as
+ * the buffer might have been exchanged during encoding of the string. */
+
+ /* Encode the inner status code */
+ if(src->hasInnerStatusCode) {
+ ret = ENCODE_WITHEXCHANGE(&src->innerStatusCode, UInt32);
+ UA_assert(ret != UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED);
+ if(ret != UA_STATUSCODE_GOOD)
+ return ret;
+ }
+
+ /* Encode the inner diagnostic info */
+ if(src->hasInnerDiagnosticInfo)
+ ret = encodeBinaryInternal(src->innerDiagnosticInfo, &UA_TYPES[UA_TYPES_DIAGNOSTICINFO], ctx);
+
+ UA_assert(ret != UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED);
+ return ret;
+}
+
+DECODE_BINARY(DiagnosticInfo) {
+ /* Decode the encoding mask */
+ u8 encodingMask;
+ status ret = DECODE_DIRECT(&encodingMask, Byte);
+ if(ret != UA_STATUSCODE_GOOD)
+ return ret;
+
+ /* Decode the content */
+ if(encodingMask & 0x01) {
+ dst->hasSymbolicId = true;
+ ret |= DECODE_DIRECT(&dst->symbolicId, UInt32); /* Int32 */
+ }
+ if(encodingMask & 0x02) {
+ dst->hasNamespaceUri = true;
+ ret |= DECODE_DIRECT(&dst->namespaceUri, UInt32); /* Int32 */
+ }
+ if(encodingMask & 0x04) {
+ dst->hasLocalizedText = true;
+ ret |= DECODE_DIRECT(&dst->localizedText, UInt32); /* Int32 */
+ }
+ if(encodingMask & 0x08) {
+ dst->hasLocale = true;
+ ret |= DECODE_DIRECT(&dst->locale, UInt32); /* Int32 */
+ }
+ if(encodingMask & 0x10) {
+ dst->hasAdditionalInfo = true;
+ ret |= DECODE_DIRECT(&dst->additionalInfo, String);
+ }
+ if(encodingMask & 0x20) {
+ dst->hasInnerStatusCode = true;
+ ret |= DECODE_DIRECT(&dst->innerStatusCode, UInt32); /* StatusCode */
+ }
+ if(encodingMask & 0x40) {
+ /* innerDiagnosticInfo is allocated on the heap */
+ dst->innerDiagnosticInfo = (UA_DiagnosticInfo*)
+ UA_calloc(1, sizeof(UA_DiagnosticInfo));
+ if(!dst->innerDiagnosticInfo)
+ return UA_STATUSCODE_BADOUTOFMEMORY;
+ dst->hasInnerDiagnosticInfo = true;
+
+ /* Check the recursion limit */
+ if(ctx->depth > UA_ENCODING_MAX_RECURSION)
+ return UA_STATUSCODE_BADENCODINGERROR;
+
+ ctx->depth++;
+ ret |= DECODE_DIRECT(dst->innerDiagnosticInfo, DiagnosticInfo);
+ ctx->depth--;
+ }
+ return ret;
+}
+
+/********************/
+/* Structured Types */
+/********************/
+
+const encodeBinarySignature encodeBinaryJumpTable[UA_BUILTIN_TYPES_COUNT + 1] = {
+ (encodeBinarySignature)Boolean_encodeBinary,
+ (encodeBinarySignature)Byte_encodeBinary, /* SByte */
+ (encodeBinarySignature)Byte_encodeBinary,
+ (encodeBinarySignature)UInt16_encodeBinary, /* Int16 */
+ (encodeBinarySignature)UInt16_encodeBinary,
+ (encodeBinarySignature)UInt32_encodeBinary, /* Int32 */
+ (encodeBinarySignature)UInt32_encodeBinary,
+ (encodeBinarySignature)UInt64_encodeBinary, /* Int64 */
+ (encodeBinarySignature)UInt64_encodeBinary,
+ (encodeBinarySignature)Float_encodeBinary,
+ (encodeBinarySignature)Double_encodeBinary,
+ (encodeBinarySignature)String_encodeBinary,
+ (encodeBinarySignature)UInt64_encodeBinary, /* DateTime */
+ (encodeBinarySignature)Guid_encodeBinary,
+ (encodeBinarySignature)String_encodeBinary, /* ByteString */
+ (encodeBinarySignature)String_encodeBinary, /* XmlElement */
+ (encodeBinarySignature)NodeId_encodeBinary,
+ (encodeBinarySignature)ExpandedNodeId_encodeBinary,
+ (encodeBinarySignature)UInt32_encodeBinary, /* StatusCode */
+ (encodeBinarySignature)encodeBinaryInternal, /* QualifiedName */
+ (encodeBinarySignature)LocalizedText_encodeBinary,
+ (encodeBinarySignature)ExtensionObject_encodeBinary,
+ (encodeBinarySignature)DataValue_encodeBinary,
+ (encodeBinarySignature)Variant_encodeBinary,
+ (encodeBinarySignature)DiagnosticInfo_encodeBinary,
+ (encodeBinarySignature)encodeBinaryInternal,
+};
+
+static status
+encodeBinaryInternal(const void *src, const UA_DataType *type, Ctx *ctx) {
+ /* Check the recursion limit */
+ if(ctx->depth > UA_ENCODING_MAX_RECURSION)
+ return UA_STATUSCODE_BADENCODINGERROR;
+ ctx->depth++;
+
+ uintptr_t ptr = (uintptr_t)src;
+ status ret = UA_STATUSCODE_GOOD;
+ u8 membersSize = type->membersSize;
+ const UA_DataType *typelists[2] = { UA_TYPES, &type[-type->typeIndex] };
+ for(size_t i = 0; i < membersSize && ret == UA_STATUSCODE_GOOD; ++i) {
+ const UA_DataTypeMember *member = &type->members[i];
+ const UA_DataType *membertype = &typelists[!member->namespaceZero][member->memberTypeIndex];
+ if(!member->isArray) {
+ ptr += member->padding;
+ size_t encode_index = membertype->builtin ? membertype->typeIndex : UA_BUILTIN_TYPES_COUNT;
+ size_t memSize = membertype->memSize;
+ u8 *oldpos = ctx->pos;
+ ret = encodeBinaryJumpTable[encode_index]((const void*)ptr, membertype, ctx);
+ ptr += memSize;
+ if(ret == UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED) {
+ ctx->pos = oldpos; /* exchange/send the buffer */
+ ret = exchangeBuffer(ctx);
+ ptr -= member->padding + memSize; /* encode the same member in the next iteration */
+ if(ret == UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED || ctx->pos + memSize > ctx->end) {
+ /* the send buffer is too small to encode the member, even after exchangeBuffer */
+ ret = UA_STATUSCODE_BADRESPONSETOOLARGE;
+ break;
+ }
+ --i;
+ }
+ } else {
+ ptr += member->padding;
+ const size_t length = *((const size_t*)ptr);
+ ptr += sizeof(size_t);
+ ret = Array_encodeBinary(*(void *UA_RESTRICT const *)ptr, length, membertype, ctx);
+ ptr += sizeof(void*);
+ }
+ }
+
+ UA_assert(ret != UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED);
+ ctx->depth--;
+ return ret;
+}
+
+status
+UA_encodeBinary(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;
+ ctx.end = *bufEnd;
+ ctx.depth = 0;
+ ctx.exchangeBufferCallback = exchangeCallback;
+ ctx.exchangeBufferCallbackHandle = exchangeHandle;
+
+ if (!ctx.pos)
+ return UA_STATUSCODE_BADINVALIDARGUMENT;
+
+ /* Encode */
+ status ret = encodeBinaryInternal(src, type, &ctx);
+
+ /* Set the new buffer position for the output. Beware that the buffer might
+ * have been exchanged internally. */
+ *bufPos = ctx.pos;
+ *bufEnd = ctx.end;
+ return ret;
+}
+
+const decodeBinarySignature decodeBinaryJumpTable[UA_BUILTIN_TYPES_COUNT + 1] = {
+ (decodeBinarySignature)Boolean_decodeBinary,
+ (decodeBinarySignature)Byte_decodeBinary, /* SByte */
+ (decodeBinarySignature)Byte_decodeBinary,
+ (decodeBinarySignature)UInt16_decodeBinary, /* Int16 */
+ (decodeBinarySignature)UInt16_decodeBinary,
+ (decodeBinarySignature)UInt32_decodeBinary, /* Int32 */
+ (decodeBinarySignature)UInt32_decodeBinary,
+ (decodeBinarySignature)UInt64_decodeBinary, /* Int64 */
+ (decodeBinarySignature)UInt64_decodeBinary,
+ (decodeBinarySignature)Float_decodeBinary,
+ (decodeBinarySignature)Double_decodeBinary,
+ (decodeBinarySignature)String_decodeBinary,
+ (decodeBinarySignature)UInt64_decodeBinary, /* DateTime */
+ (decodeBinarySignature)Guid_decodeBinary,
+ (decodeBinarySignature)String_decodeBinary, /* ByteString */
+ (decodeBinarySignature)String_decodeBinary, /* XmlElement */
+ (decodeBinarySignature)NodeId_decodeBinary,
+ (decodeBinarySignature)ExpandedNodeId_decodeBinary,
+ (decodeBinarySignature)UInt32_decodeBinary, /* StatusCode */
+ (decodeBinarySignature)decodeBinaryInternal, /* QualifiedName */
+ (decodeBinarySignature)LocalizedText_decodeBinary,
+ (decodeBinarySignature)ExtensionObject_decodeBinary,
+ (decodeBinarySignature)DataValue_decodeBinary,
+ (decodeBinarySignature)Variant_decodeBinary,
+ (decodeBinarySignature)DiagnosticInfo_decodeBinary,
+ (decodeBinarySignature)decodeBinaryInternal
+};
+
+static status
+decodeBinaryInternal(void *dst, const UA_DataType *type, Ctx *ctx) {
+ /* Check the recursion limit */
+ if(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] };
+ for(size_t i = 0; i < membersSize && ret == UA_STATUSCODE_GOOD; ++i) {
+ const UA_DataTypeMember *member = &type->members[i];
+ const UA_DataType *membertype = &typelists[!member->namespaceZero][member->memberTypeIndex];
+ if(!member->isArray) {
+ ptr += member->padding;
+ size_t fi = membertype->builtin ? membertype->typeIndex : UA_BUILTIN_TYPES_COUNT;
+ size_t memSize = membertype->memSize;
+ ret |= decodeBinaryJumpTable[fi]((void *UA_RESTRICT)ptr, membertype, ctx);
+ ptr += memSize;
+ } else {
+ ptr += member->padding;
+ size_t *length = (size_t*)ptr;
+ ptr += sizeof(size_t);
+ ret |= Array_decodeBinary((void *UA_RESTRICT *UA_RESTRICT)ptr, length, membertype, ctx);
+ ptr += sizeof(void*);
+ }
+ }
+
+ ctx->depth--;
+ return ret;
+}
+
+status
+UA_decodeBinary(const UA_ByteString *src, size_t *offset, void *dst,
+ const UA_DataType *type, size_t customTypesSize,
+ const UA_DataType *customTypes) {
+ /* Set up the context */
+ Ctx ctx;
+ ctx.pos = &src->data[*offset];
+ ctx.end = &src->data[src->length];
+ ctx.depth = 0;
+ ctx.customTypesArraySize = customTypesSize;
+ ctx.customTypesArray = customTypes;
+
+ /* Decode */
+ memset(dst, 0, type->memSize); /* Initialize the value */
+ status ret = decodeBinaryInternal(dst, type, &ctx);
+
+ if(ret == UA_STATUSCODE_GOOD) {
+ /* Set the new offset */
+ *offset = (size_t)(ctx.pos - src->data) / sizeof(u8);
+ } else {
+ /* Clean up */
+ UA_deleteMembers(dst, type);
+ memset(dst, 0, type->memSize);
+ }
+ return ret;
+}
+
+/**
+ * Compute the Message Size
+ * ------------------------
+ * The following methods are used to compute the length of a datum in binary
+ * encoding. */
+
+static size_t
+Array_calcSizeBinary(const void *src, size_t length, const UA_DataType *type) {
+ size_t s = 4; /* length */
+ if(type->overlayable) {
+ s += type->memSize * length;
+ return s;
+ }
+ uintptr_t ptr = (uintptr_t)src;
+ size_t encode_index = type->builtin ? type->typeIndex : UA_BUILTIN_TYPES_COUNT;
+ for(size_t i = 0; i < length; ++i) {
+ s += calcSizeBinaryJumpTable[encode_index]((const void*)ptr, type);
+ ptr += type->memSize;
+ }
+ return s;
+}
+
+static size_t
+calcSizeBinaryMemSize(const void *UA_RESTRICT p, const UA_DataType *type) {
+ return type->memSize;
+}
+
+CALCSIZE_BINARY(String) {
+ return 4 + src->length;
+}
+
+CALCSIZE_BINARY(Guid) {
+ return 16;
+}
+
+CALCSIZE_BINARY(NodeId) {
+ size_t s = 1; /* encoding byte */
+ switch(src->identifierType) {
+ case UA_NODEIDTYPE_NUMERIC:
+ if(src->identifier.numeric > UA_UINT16_MAX || src->namespaceIndex > UA_BYTE_MAX) {
+ s += 6;
+ } else if(src->identifier.numeric > UA_BYTE_MAX || src->namespaceIndex > 0) {
+ s += 3;
+ } else {
+ s += 1;
+ }
+ break;
+ case UA_NODEIDTYPE_BYTESTRING:
+ case UA_NODEIDTYPE_STRING:
+ s += 2;
+ s += String_calcSizeBinary(&src->identifier.string, NULL);
+ break;
+ case UA_NODEIDTYPE_GUID:
+ s += 18;
+ break;
+ default:
+ return 0;
+ }
+ return s;
+}
+
+CALCSIZE_BINARY(ExpandedNodeId) {
+ size_t s = NodeId_calcSizeBinary(&src->nodeId, NULL);
+ if(src->namespaceUri.length > 0)
+ s += String_calcSizeBinary(&src->namespaceUri, NULL);
+ if(src->serverIndex > 0)
+ s += 4;
+ return s;
+}
+
+CALCSIZE_BINARY(LocalizedText) {
+ size_t s = 1; /* encoding byte */
+ if(src->locale.data)
+ s += String_calcSizeBinary(&src->locale, NULL);
+ if(src->text.data)
+ s += String_calcSizeBinary(&src->text, NULL);
+ return s;
+}
+
+CALCSIZE_BINARY(ExtensionObject) {
+ size_t s = 1; /* encoding byte */
+ if(src->encoding > UA_EXTENSIONOBJECT_ENCODED_XML) {
+ if(!src->content.decoded.type || !src->content.decoded.data)
+ return 0;
+ if(src->content.decoded.type->typeId.identifierType != UA_NODEIDTYPE_NUMERIC)
+ return 0;
+ s += NodeId_calcSizeBinary(&src->content.decoded.type->typeId, NULL);
+ s += 4; /* length */
+ const UA_DataType *type = src->content.decoded.type;
+ size_t encode_index = type->builtin ? type->typeIndex : UA_BUILTIN_TYPES_COUNT;
+ s += calcSizeBinaryJumpTable[encode_index](src->content.decoded.data, type);
+ } else {
+ s += NodeId_calcSizeBinary(&src->content.encoded.typeId, NULL);
+ switch(src->encoding) {
+ case UA_EXTENSIONOBJECT_ENCODED_NOBODY:
+ break;
+ case UA_EXTENSIONOBJECT_ENCODED_BYTESTRING:
+ case UA_EXTENSIONOBJECT_ENCODED_XML:
+ s += String_calcSizeBinary(&src->content.encoded.body, NULL);
+ break;
+ default:
+ return 0;
+ }
+ }
+ return s;
+}
+
+CALCSIZE_BINARY(Variant) {
+ size_t s = 1; /* encoding byte */
+ if(!src->type)
+ return s;
+
+ bool isArray = src->arrayLength > 0 || src->data <= UA_EMPTY_ARRAY_SENTINEL;
+ bool hasDimensions = isArray && src->arrayDimensionsSize > 0;
+ bool isBuiltin = src->type->builtin;
+
+
+ size_t encode_index = src->type->typeIndex;
+ if(!isBuiltin) {
+ encode_index = UA_BUILTIN_TYPES_COUNT;
+ if(src->type->typeId.identifierType != UA_NODEIDTYPE_NUMERIC)
+ return 0;
+ }
+
+ uintptr_t ptr = (uintptr_t)src->data;
+ size_t length = isArray ? src->arrayLength : 1;
+ if (isArray)
+ s += Array_calcSizeBinary((const void*)ptr, length, src->type);
+ else
+ s += calcSizeBinaryJumpTable[encode_index]((const void*)ptr, src->type);
+
+ if (!isBuiltin) {
+ /* The type is wrapped inside an extensionobject */
+ /* (NodeId + encoding byte + extension object length) * array length */
+ s += (NodeId_calcSizeBinary(&src->type->typeId, NULL) + 1 + 4) * length;
+ }
+
+ if(hasDimensions)
+ s += Array_calcSizeBinary(src->arrayDimensions, src->arrayDimensionsSize,
+ &UA_TYPES[UA_TYPES_INT32]);
+ return s;
+}
+
+CALCSIZE_BINARY(DataValue) {
+ size_t s = 1; /* encoding byte */
+ if(src->hasValue)
+ s += Variant_calcSizeBinary(&src->value, NULL);
+ if(src->hasStatus)
+ s += 4;
+ if(src->hasSourceTimestamp)
+ s += 8;
+ if(src->hasSourcePicoseconds)
+ s += 2;
+ if(src->hasServerTimestamp)
+ s += 8;
+ if(src->hasServerPicoseconds)
+ s += 2;
+ return s;
+}
+
+CALCSIZE_BINARY(DiagnosticInfo) {
+ size_t s = 1; /* encoding byte */
+ if(src->hasSymbolicId)
+ s += 4;
+ if(src->hasNamespaceUri)
+ s += 4;
+ if(src->hasLocalizedText)
+ s += 4;
+ if(src->hasLocale)
+ s += 4;
+ if(src->hasAdditionalInfo)
+ s += String_calcSizeBinary(&src->additionalInfo, NULL);
+ if(src->hasInnerStatusCode)
+ s += 4;
+ if(src->hasInnerDiagnosticInfo)
+ s += DiagnosticInfo_calcSizeBinary(src->innerDiagnosticInfo, NULL);
+ return s;
+}
+
+const calcSizeBinarySignature calcSizeBinaryJumpTable[UA_BUILTIN_TYPES_COUNT + 1] = {
+ (calcSizeBinarySignature)calcSizeBinaryMemSize, /* Boolean */
+ (calcSizeBinarySignature)calcSizeBinaryMemSize, /* Byte */
+ (calcSizeBinarySignature)calcSizeBinaryMemSize,
+ (calcSizeBinarySignature)calcSizeBinaryMemSize, /* Int16 */
+ (calcSizeBinarySignature)calcSizeBinaryMemSize,
+ (calcSizeBinarySignature)calcSizeBinaryMemSize, /* Int32 */
+ (calcSizeBinarySignature)calcSizeBinaryMemSize,
+ (calcSizeBinarySignature)calcSizeBinaryMemSize, /* Int64 */
+ (calcSizeBinarySignature)calcSizeBinaryMemSize,
+ (calcSizeBinarySignature)calcSizeBinaryMemSize, /* Float */
+ (calcSizeBinarySignature)calcSizeBinaryMemSize, /* Double */
+ (calcSizeBinarySignature)String_calcSizeBinary,
+ (calcSizeBinarySignature)calcSizeBinaryMemSize, /* DateTime */
+ (calcSizeBinarySignature)Guid_calcSizeBinary,
+ (calcSizeBinarySignature)String_calcSizeBinary, /* ByteString */
+ (calcSizeBinarySignature)String_calcSizeBinary, /* XmlElement */
+ (calcSizeBinarySignature)NodeId_calcSizeBinary,
+ (calcSizeBinarySignature)ExpandedNodeId_calcSizeBinary,
+ (calcSizeBinarySignature)calcSizeBinaryMemSize, /* StatusCode */
+ (calcSizeBinarySignature)UA_calcSizeBinary, /* QualifiedName */
+ (calcSizeBinarySignature)LocalizedText_calcSizeBinary,
+ (calcSizeBinarySignature)ExtensionObject_calcSizeBinary,
+ (calcSizeBinarySignature)DataValue_calcSizeBinary,
+ (calcSizeBinarySignature)Variant_calcSizeBinary,
+ (calcSizeBinarySignature)DiagnosticInfo_calcSizeBinary,
+ (calcSizeBinarySignature)UA_calcSizeBinary
+};
+
+size_t
+UA_calcSizeBinary(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] };
+ for(size_t i = 0; i < membersSize; ++i) {
+ const UA_DataTypeMember *member = &type->members[i];
+ const UA_DataType *membertype = &typelists[!member->namespaceZero][member->memberTypeIndex];
+ if(!member->isArray) {
+ ptr += member->padding;
+ size_t encode_index = membertype->builtin ? membertype->typeIndex : UA_BUILTIN_TYPES_COUNT;
+ s += calcSizeBinaryJumpTable[encode_index]((const void*)ptr, membertype);
+ ptr += membertype->memSize;
+ } else {
+ ptr += member->padding;
+ const size_t length = *((const size_t*)ptr);
+ ptr += sizeof(size_t);
+ s += Array_calcSizeBinary(*(void *UA_RESTRICT const *)ptr, length, membertype);
+ ptr += sizeof(void*);
+ }
+ }
+ return s;
+}
+
+/*********************************** amalgamated original file "/home/jvoe/open62541/build/src_generated/ua_types_generated.c" ***********************************/
+
+/* Generated from Opc.Ua.Types.bsd with script /home/jvoe/open62541/tools/generate_datatypes.py
+ * on host rigel by user jvoe at 2019-01-04 01:18:40 */
+
+
+/* Boolean */
+static UA_DataTypeMember Boolean_members[1] = {
+{
+ UA_TYPENAME("") /* .memberName */
+ UA_TYPES_BOOLEAN, /* .memberTypeIndex */
+ 0, /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+}};
+
+/* SByte */
+static UA_DataTypeMember SByte_members[1] = {
+{
+ UA_TYPENAME("") /* .memberName */
+ UA_TYPES_SBYTE, /* .memberTypeIndex */
+ 0, /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+}};
+
+/* Byte */
+static UA_DataTypeMember Byte_members[1] = {
+{
+ UA_TYPENAME("") /* .memberName */
+ UA_TYPES_BYTE, /* .memberTypeIndex */
+ 0, /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+}};
+
+/* Int16 */
+static UA_DataTypeMember Int16_members[1] = {
+{
+ UA_TYPENAME("") /* .memberName */
+ UA_TYPES_INT16, /* .memberTypeIndex */
+ 0, /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+}};
+
+/* UInt16 */
+static UA_DataTypeMember UInt16_members[1] = {
+{
+ UA_TYPENAME("") /* .memberName */
+ UA_TYPES_UINT16, /* .memberTypeIndex */
+ 0, /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+}};
+
+/* Int32 */
+static UA_DataTypeMember Int32_members[1] = {
+{
+ UA_TYPENAME("") /* .memberName */
+ UA_TYPES_INT32, /* .memberTypeIndex */
+ 0, /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+}};
+
+/* UInt32 */
+static UA_DataTypeMember UInt32_members[1] = {
+{
+ UA_TYPENAME("") /* .memberName */
+ UA_TYPES_UINT32, /* .memberTypeIndex */
+ 0, /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+}};
+
+/* Int64 */
+static UA_DataTypeMember Int64_members[1] = {
+{
+ UA_TYPENAME("") /* .memberName */
+ UA_TYPES_INT64, /* .memberTypeIndex */
+ 0, /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+}};
+
+/* UInt64 */
+static UA_DataTypeMember UInt64_members[1] = {
+{
+ UA_TYPENAME("") /* .memberName */
+ UA_TYPES_UINT64, /* .memberTypeIndex */
+ 0, /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+}};
+
+/* Float */
+static UA_DataTypeMember Float_members[1] = {
+{
+ UA_TYPENAME("") /* .memberName */
+ UA_TYPES_FLOAT, /* .memberTypeIndex */
+ 0, /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+}};
+
+/* Double */
+static UA_DataTypeMember Double_members[1] = {
+{
+ UA_TYPENAME("") /* .memberName */
+ UA_TYPES_DOUBLE, /* .memberTypeIndex */
+ 0, /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+}};
+
+/* String */
+static UA_DataTypeMember String_members[1] = {
+{
+ UA_TYPENAME("") /* .memberName */
+ UA_TYPES_BYTE, /* .memberTypeIndex */
+ 0, /* .padding */
+ true, /* .namespaceZero */
+ true /* .isArray */
+}};
+
+/* DateTime */
+static UA_DataTypeMember DateTime_members[1] = {
+{
+ UA_TYPENAME("") /* .memberName */
+ UA_TYPES_DATETIME, /* .memberTypeIndex */
+ 0, /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+}};
+
+/* Guid */
+static UA_DataTypeMember Guid_members[1] = {
+{
+ UA_TYPENAME("") /* .memberName */
+ UA_TYPES_GUID, /* .memberTypeIndex */
+ 0, /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+}};
+
+/* ByteString */
+static UA_DataTypeMember ByteString_members[1] = {
+{
+ UA_TYPENAME("") /* .memberName */
+ UA_TYPES_BYTE, /* .memberTypeIndex */
+ 0, /* .padding */
+ true, /* .namespaceZero */
+ true /* .isArray */
+}};
+
+/* XmlElement */
+static UA_DataTypeMember XmlElement_members[1] = {
+{
+ UA_TYPENAME("") /* .memberName */
+ UA_TYPES_BYTE, /* .memberTypeIndex */
+ 0, /* .padding */
+ true, /* .namespaceZero */
+ true /* .isArray */
+}};
+
+/* NodeId */
+static UA_DataTypeMember NodeId_members[1] = {
+{
+ UA_TYPENAME("") /* .memberName */
+ UA_TYPES_NODEID, /* .memberTypeIndex */
+ 0, /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+}};
+
+/* ExpandedNodeId */
+static UA_DataTypeMember ExpandedNodeId_members[1] = {
+{
+ UA_TYPENAME("") /* .memberName */
+ UA_TYPES_EXPANDEDNODEID, /* .memberTypeIndex */
+ 0, /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+}};
+
+/* StatusCode */
+static UA_DataTypeMember StatusCode_members[1] = {
+{
+ UA_TYPENAME("") /* .memberName */
+ UA_TYPES_STATUSCODE, /* .memberTypeIndex */
+ 0, /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+}};
+
+/* QualifiedName */
+static UA_DataTypeMember QualifiedName_members[2] = {
+{
+ UA_TYPENAME("namespaceIndex") /* .memberName */
+ UA_TYPES_INT16, /* .memberTypeIndex */
+ 0, /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("name") /* .memberName */
+ UA_TYPES_STRING, /* .memberTypeIndex */
+ offsetof(UA_QualifiedName, name) - offsetof(UA_QualifiedName, namespaceIndex) - sizeof(UA_Int16), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+}};
+
+/* LocalizedText */
+static UA_DataTypeMember LocalizedText_members[1] = {
+{
+ UA_TYPENAME("") /* .memberName */
+ UA_TYPES_LOCALIZEDTEXT, /* .memberTypeIndex */
+ 0, /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+}};
+
+/* ExtensionObject */
+static UA_DataTypeMember ExtensionObject_members[1] = {
+{
+ UA_TYPENAME("") /* .memberName */
+ UA_TYPES_EXTENSIONOBJECT, /* .memberTypeIndex */
+ 0, /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+}};
+
+/* DataValue */
+static UA_DataTypeMember DataValue_members[1] = {
+{
+ UA_TYPENAME("") /* .memberName */
+ UA_TYPES_DATAVALUE, /* .memberTypeIndex */
+ 0, /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+}};
+
+/* Variant */
+static UA_DataTypeMember Variant_members[1] = {
+{
+ UA_TYPENAME("") /* .memberName */
+ UA_TYPES_VARIANT, /* .memberTypeIndex */
+ 0, /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+}};
+
+/* DiagnosticInfo */
+static UA_DataTypeMember DiagnosticInfo_members[1] = {
+{
+ UA_TYPENAME("") /* .memberName */
+ UA_TYPES_DIAGNOSTICINFO, /* .memberTypeIndex */
+ 0, /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+}};
+
+/* SignedSoftwareCertificate */
+static UA_DataTypeMember SignedSoftwareCertificate_members[2] = {
+{
+ UA_TYPENAME("certificateData") /* .memberName */
+ UA_TYPES_BYTESTRING, /* .memberTypeIndex */
+ 0, /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("signature") /* .memberName */
+ UA_TYPES_BYTESTRING, /* .memberTypeIndex */
+ offsetof(UA_SignedSoftwareCertificate, signature) - offsetof(UA_SignedSoftwareCertificate, certificateData) - sizeof(UA_ByteString), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+}};
+
+/* SemanticChangeStructureDataType */
+static UA_DataTypeMember SemanticChangeStructureDataType_members[2] = {
+{
+ UA_TYPENAME("affected") /* .memberName */
+ UA_TYPES_NODEID, /* .memberTypeIndex */
+ 0, /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("affectedType") /* .memberName */
+ UA_TYPES_NODEID, /* .memberTypeIndex */
+ offsetof(UA_SemanticChangeStructureDataType, affectedType) - offsetof(UA_SemanticChangeStructureDataType, affected) - sizeof(UA_NodeId), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+}};
+
+/* StatusChangeNotification */
+static UA_DataTypeMember StatusChangeNotification_members[2] = {
+{
+ UA_TYPENAME("status") /* .memberName */
+ UA_TYPES_STATUSCODE, /* .memberTypeIndex */
+ 0, /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("diagnosticInfo") /* .memberName */
+ UA_TYPES_DIAGNOSTICINFO, /* .memberTypeIndex */
+ offsetof(UA_StatusChangeNotification, diagnosticInfo) - offsetof(UA_StatusChangeNotification, status) - sizeof(UA_StatusCode), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+}};
+
+/* BrowsePathTarget */
+static UA_DataTypeMember BrowsePathTarget_members[2] = {
+{
+ UA_TYPENAME("targetId") /* .memberName */
+ UA_TYPES_EXPANDEDNODEID, /* .memberTypeIndex */
+ 0, /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("remainingPathIndex") /* .memberName */
+ UA_TYPES_UINT32, /* .memberTypeIndex */
+ offsetof(UA_BrowsePathTarget, remainingPathIndex) - offsetof(UA_BrowsePathTarget, targetId) - sizeof(UA_ExpandedNodeId), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+}};
+
+/* ViewAttributes */
+static UA_DataTypeMember ViewAttributes_members[7] = {
+{
+ UA_TYPENAME("specifiedAttributes") /* .memberName */
+ UA_TYPES_UINT32, /* .memberTypeIndex */
+ 0, /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("displayName") /* .memberName */
+ UA_TYPES_LOCALIZEDTEXT, /* .memberTypeIndex */
+ offsetof(UA_ViewAttributes, displayName) - offsetof(UA_ViewAttributes, specifiedAttributes) - sizeof(UA_UInt32), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("description") /* .memberName */
+ UA_TYPES_LOCALIZEDTEXT, /* .memberTypeIndex */
+ offsetof(UA_ViewAttributes, description) - offsetof(UA_ViewAttributes, displayName) - sizeof(UA_LocalizedText), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("writeMask") /* .memberName */
+ UA_TYPES_UINT32, /* .memberTypeIndex */
+ offsetof(UA_ViewAttributes, writeMask) - offsetof(UA_ViewAttributes, description) - sizeof(UA_LocalizedText), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("userWriteMask") /* .memberName */
+ UA_TYPES_UINT32, /* .memberTypeIndex */
+ offsetof(UA_ViewAttributes, userWriteMask) - offsetof(UA_ViewAttributes, writeMask) - sizeof(UA_UInt32), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("containsNoLoops") /* .memberName */
+ UA_TYPES_BOOLEAN, /* .memberTypeIndex */
+ offsetof(UA_ViewAttributes, containsNoLoops) - offsetof(UA_ViewAttributes, userWriteMask) - sizeof(UA_UInt32), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("eventNotifier") /* .memberName */
+ UA_TYPES_BYTE, /* .memberTypeIndex */
+ offsetof(UA_ViewAttributes, eventNotifier) - offsetof(UA_ViewAttributes, containsNoLoops) - sizeof(UA_Boolean), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+}};
+
+/* RequestHeader */
+static UA_DataTypeMember RequestHeader_members[7] = {
+{
+ UA_TYPENAME("authenticationToken") /* .memberName */
+ UA_TYPES_NODEID, /* .memberTypeIndex */
+ 0, /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("timestamp") /* .memberName */
+ UA_TYPES_DATETIME, /* .memberTypeIndex */
+ offsetof(UA_RequestHeader, timestamp) - offsetof(UA_RequestHeader, authenticationToken) - sizeof(UA_NodeId), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("requestHandle") /* .memberName */
+ UA_TYPES_UINT32, /* .memberTypeIndex */
+ offsetof(UA_RequestHeader, requestHandle) - offsetof(UA_RequestHeader, timestamp) - sizeof(UA_DateTime), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("returnDiagnostics") /* .memberName */
+ UA_TYPES_UINT32, /* .memberTypeIndex */
+ offsetof(UA_RequestHeader, returnDiagnostics) - offsetof(UA_RequestHeader, requestHandle) - sizeof(UA_UInt32), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("auditEntryId") /* .memberName */
+ UA_TYPES_STRING, /* .memberTypeIndex */
+ offsetof(UA_RequestHeader, auditEntryId) - offsetof(UA_RequestHeader, returnDiagnostics) - sizeof(UA_UInt32), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("timeoutHint") /* .memberName */
+ UA_TYPES_UINT32, /* .memberTypeIndex */
+ offsetof(UA_RequestHeader, timeoutHint) - offsetof(UA_RequestHeader, auditEntryId) - sizeof(UA_String), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("additionalHeader") /* .memberName */
+ UA_TYPES_EXTENSIONOBJECT, /* .memberTypeIndex */
+ offsetof(UA_RequestHeader, additionalHeader) - offsetof(UA_RequestHeader, timeoutHint) - sizeof(UA_UInt32), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+}};
+
+/* MonitoredItemModifyResult */
+static UA_DataTypeMember MonitoredItemModifyResult_members[4] = {
+{
+ UA_TYPENAME("statusCode") /* .memberName */
+ UA_TYPES_STATUSCODE, /* .memberTypeIndex */
+ 0, /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("revisedSamplingInterval") /* .memberName */
+ UA_TYPES_DOUBLE, /* .memberTypeIndex */
+ offsetof(UA_MonitoredItemModifyResult, revisedSamplingInterval) - offsetof(UA_MonitoredItemModifyResult, statusCode) - sizeof(UA_StatusCode), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("revisedQueueSize") /* .memberName */
+ UA_TYPES_UINT32, /* .memberTypeIndex */
+ offsetof(UA_MonitoredItemModifyResult, revisedQueueSize) - offsetof(UA_MonitoredItemModifyResult, revisedSamplingInterval) - sizeof(UA_Double), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("filterResult") /* .memberName */
+ UA_TYPES_EXTENSIONOBJECT, /* .memberTypeIndex */
+ offsetof(UA_MonitoredItemModifyResult, filterResult) - offsetof(UA_MonitoredItemModifyResult, revisedQueueSize) - sizeof(UA_UInt32), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+}};
+
+/* ElementOperand */
+static UA_DataTypeMember ElementOperand_members[1] = {
+{
+ UA_TYPENAME("index") /* .memberName */
+ UA_TYPES_UINT32, /* .memberTypeIndex */
+ 0, /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+}};
+
+/* CloseSecureChannelRequest */
+static UA_DataTypeMember CloseSecureChannelRequest_members[1] = {
+{
+ UA_TYPENAME("requestHeader") /* .memberName */
+ UA_TYPES_REQUESTHEADER, /* .memberTypeIndex */
+ 0, /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+}};
+
+/* AddNodesResult */
+static UA_DataTypeMember AddNodesResult_members[2] = {
+{
+ UA_TYPENAME("statusCode") /* .memberName */
+ UA_TYPES_STATUSCODE, /* .memberTypeIndex */
+ 0, /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("addedNodeId") /* .memberName */
+ UA_TYPES_NODEID, /* .memberTypeIndex */
+ offsetof(UA_AddNodesResult, addedNodeId) - offsetof(UA_AddNodesResult, statusCode) - sizeof(UA_StatusCode), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+}};
+
+/* VariableAttributes */
+static UA_DataTypeMember VariableAttributes_members[13] = {
+{
+ UA_TYPENAME("specifiedAttributes") /* .memberName */
+ UA_TYPES_UINT32, /* .memberTypeIndex */
+ 0, /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("displayName") /* .memberName */
+ UA_TYPES_LOCALIZEDTEXT, /* .memberTypeIndex */
+ offsetof(UA_VariableAttributes, displayName) - offsetof(UA_VariableAttributes, specifiedAttributes) - sizeof(UA_UInt32), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("description") /* .memberName */
+ UA_TYPES_LOCALIZEDTEXT, /* .memberTypeIndex */
+ offsetof(UA_VariableAttributes, description) - offsetof(UA_VariableAttributes, displayName) - sizeof(UA_LocalizedText), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("writeMask") /* .memberName */
+ UA_TYPES_UINT32, /* .memberTypeIndex */
+ offsetof(UA_VariableAttributes, writeMask) - offsetof(UA_VariableAttributes, description) - sizeof(UA_LocalizedText), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("userWriteMask") /* .memberName */
+ UA_TYPES_UINT32, /* .memberTypeIndex */
+ offsetof(UA_VariableAttributes, userWriteMask) - offsetof(UA_VariableAttributes, writeMask) - sizeof(UA_UInt32), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("value") /* .memberName */
+ UA_TYPES_VARIANT, /* .memberTypeIndex */
+ offsetof(UA_VariableAttributes, value) - offsetof(UA_VariableAttributes, userWriteMask) - sizeof(UA_UInt32), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("dataType") /* .memberName */
+ UA_TYPES_NODEID, /* .memberTypeIndex */
+ offsetof(UA_VariableAttributes, dataType) - offsetof(UA_VariableAttributes, value) - sizeof(UA_Variant), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("valueRank") /* .memberName */
+ UA_TYPES_INT32, /* .memberTypeIndex */
+ offsetof(UA_VariableAttributes, valueRank) - offsetof(UA_VariableAttributes, dataType) - sizeof(UA_NodeId), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("arrayDimensions") /* .memberName */
+ UA_TYPES_UINT32, /* .memberTypeIndex */
+ offsetof(UA_VariableAttributes, arrayDimensionsSize) - offsetof(UA_VariableAttributes, valueRank) - sizeof(UA_Int32), /* .padding */
+ true, /* .namespaceZero */
+ true /* .isArray */
+},
+{
+ UA_TYPENAME("accessLevel") /* .memberName */
+ UA_TYPES_BYTE, /* .memberTypeIndex */
+ offsetof(UA_VariableAttributes, accessLevel) - offsetof(UA_VariableAttributes, arrayDimensions) - sizeof(void*), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("userAccessLevel") /* .memberName */
+ UA_TYPES_BYTE, /* .memberTypeIndex */
+ offsetof(UA_VariableAttributes, userAccessLevel) - offsetof(UA_VariableAttributes, accessLevel) - sizeof(UA_Byte), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("minimumSamplingInterval") /* .memberName */
+ UA_TYPES_DOUBLE, /* .memberTypeIndex */
+ offsetof(UA_VariableAttributes, minimumSamplingInterval) - offsetof(UA_VariableAttributes, userAccessLevel) - sizeof(UA_Byte), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("historizing") /* .memberName */
+ UA_TYPES_BOOLEAN, /* .memberTypeIndex */
+ offsetof(UA_VariableAttributes, historizing) - offsetof(UA_VariableAttributes, minimumSamplingInterval) - sizeof(UA_Double), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+}};
+
+/* NotificationMessage */
+static UA_DataTypeMember NotificationMessage_members[3] = {
+{
+ UA_TYPENAME("sequenceNumber") /* .memberName */
+ UA_TYPES_UINT32, /* .memberTypeIndex */
+ 0, /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("publishTime") /* .memberName */
+ UA_TYPES_DATETIME, /* .memberTypeIndex */
+ offsetof(UA_NotificationMessage, publishTime) - offsetof(UA_NotificationMessage, sequenceNumber) - sizeof(UA_UInt32), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("notificationData") /* .memberName */
+ UA_TYPES_EXTENSIONOBJECT, /* .memberTypeIndex */
+ offsetof(UA_NotificationMessage, notificationDataSize) - offsetof(UA_NotificationMessage, publishTime) - sizeof(UA_DateTime), /* .padding */
+ true, /* .namespaceZero */
+ true /* .isArray */
+}};
+
+/* FindServersOnNetworkRequest */
+static UA_DataTypeMember FindServersOnNetworkRequest_members[4] = {
+{
+ UA_TYPENAME("requestHeader") /* .memberName */
+ UA_TYPES_REQUESTHEADER, /* .memberTypeIndex */
+ 0, /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("startingRecordId") /* .memberName */
+ UA_TYPES_UINT32, /* .memberTypeIndex */
+ offsetof(UA_FindServersOnNetworkRequest, startingRecordId) - offsetof(UA_FindServersOnNetworkRequest, requestHeader) - sizeof(UA_RequestHeader), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("maxRecordsToReturn") /* .memberName */
+ UA_TYPES_UINT32, /* .memberTypeIndex */
+ offsetof(UA_FindServersOnNetworkRequest, maxRecordsToReturn) - offsetof(UA_FindServersOnNetworkRequest, startingRecordId) - sizeof(UA_UInt32), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("serverCapabilityFilter") /* .memberName */
+ UA_TYPES_STRING, /* .memberTypeIndex */
+ offsetof(UA_FindServersOnNetworkRequest, serverCapabilityFilterSize) - offsetof(UA_FindServersOnNetworkRequest, maxRecordsToReturn) - sizeof(UA_UInt32), /* .padding */
+ true, /* .namespaceZero */
+ true /* .isArray */
+}};
+
+/* EventFieldList */
+static UA_DataTypeMember EventFieldList_members[2] = {
+{
+ UA_TYPENAME("clientHandle") /* .memberName */
+ UA_TYPES_UINT32, /* .memberTypeIndex */
+ 0, /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("eventFields") /* .memberName */
+ UA_TYPES_VARIANT, /* .memberTypeIndex */
+ offsetof(UA_EventFieldList, eventFieldsSize) - offsetof(UA_EventFieldList, clientHandle) - sizeof(UA_UInt32), /* .padding */
+ true, /* .namespaceZero */
+ true /* .isArray */
+}};
+
+/* MonitoringMode */
+static UA_DataTypeMember MonitoringMode_members[1] = {
+{
+ UA_TYPENAME("") /* .memberName */
+ UA_TYPES_INT32, /* .memberTypeIndex */
+ 0, /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+}};
+
+/* MdnsDiscoveryConfiguration */
+static UA_DataTypeMember MdnsDiscoveryConfiguration_members[2] = {
+{
+ UA_TYPENAME("mdnsServerName") /* .memberName */
+ UA_TYPES_STRING, /* .memberTypeIndex */
+ 0, /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("serverCapabilities") /* .memberName */
+ UA_TYPES_STRING, /* .memberTypeIndex */
+ offsetof(UA_MdnsDiscoveryConfiguration, serverCapabilitiesSize) - offsetof(UA_MdnsDiscoveryConfiguration, mdnsServerName) - sizeof(UA_String), /* .padding */
+ true, /* .namespaceZero */
+ true /* .isArray */
+}};
+
+/* CallMethodResult */
+static UA_DataTypeMember CallMethodResult_members[4] = {
+{
+ UA_TYPENAME("statusCode") /* .memberName */
+ UA_TYPES_STATUSCODE, /* .memberTypeIndex */
+ 0, /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("inputArgumentResults") /* .memberName */
+ UA_TYPES_STATUSCODE, /* .memberTypeIndex */
+ offsetof(UA_CallMethodResult, inputArgumentResultsSize) - offsetof(UA_CallMethodResult, statusCode) - sizeof(UA_StatusCode), /* .padding */
+ true, /* .namespaceZero */
+ true /* .isArray */
+},
+{
+ UA_TYPENAME("inputArgumentDiagnosticInfos") /* .memberName */
+ UA_TYPES_DIAGNOSTICINFO, /* .memberTypeIndex */
+ offsetof(UA_CallMethodResult, inputArgumentDiagnosticInfosSize) - offsetof(UA_CallMethodResult, inputArgumentResults) - sizeof(void*), /* .padding */
+ true, /* .namespaceZero */
+ true /* .isArray */
+},
+{
+ UA_TYPENAME("outputArguments") /* .memberName */
+ UA_TYPES_VARIANT, /* .memberTypeIndex */
+ offsetof(UA_CallMethodResult, outputArgumentsSize) - offsetof(UA_CallMethodResult, inputArgumentDiagnosticInfos) - sizeof(void*), /* .padding */
+ true, /* .namespaceZero */
+ true /* .isArray */
+}};
+
+/* ParsingResult */
+static UA_DataTypeMember ParsingResult_members[3] = {
+{
+ UA_TYPENAME("statusCode") /* .memberName */
+ UA_TYPES_STATUSCODE, /* .memberTypeIndex */
+ 0, /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("dataStatusCodes") /* .memberName */
+ UA_TYPES_STATUSCODE, /* .memberTypeIndex */
+ offsetof(UA_ParsingResult, dataStatusCodesSize) - offsetof(UA_ParsingResult, statusCode) - sizeof(UA_StatusCode), /* .padding */
+ true, /* .namespaceZero */
+ true /* .isArray */
+},
+{
+ UA_TYPENAME("dataDiagnosticInfos") /* .memberName */
+ UA_TYPES_DIAGNOSTICINFO, /* .memberTypeIndex */
+ offsetof(UA_ParsingResult, dataDiagnosticInfosSize) - offsetof(UA_ParsingResult, dataStatusCodes) - sizeof(void*), /* .padding */
+ true, /* .namespaceZero */
+ true /* .isArray */
+}};
+
+/* RelativePathElement */
+static UA_DataTypeMember RelativePathElement_members[4] = {
+{
+ UA_TYPENAME("referenceTypeId") /* .memberName */
+ UA_TYPES_NODEID, /* .memberTypeIndex */
+ 0, /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("isInverse") /* .memberName */
+ UA_TYPES_BOOLEAN, /* .memberTypeIndex */
+ offsetof(UA_RelativePathElement, isInverse) - offsetof(UA_RelativePathElement, referenceTypeId) - sizeof(UA_NodeId), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("includeSubtypes") /* .memberName */
+ UA_TYPES_BOOLEAN, /* .memberTypeIndex */
+ offsetof(UA_RelativePathElement, includeSubtypes) - offsetof(UA_RelativePathElement, isInverse) - sizeof(UA_Boolean), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("targetName") /* .memberName */
+ UA_TYPES_QUALIFIEDNAME, /* .memberTypeIndex */
+ offsetof(UA_RelativePathElement, targetName) - offsetof(UA_RelativePathElement, includeSubtypes) - sizeof(UA_Boolean), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+}};
+
+/* BrowseDirection */
+static UA_DataTypeMember BrowseDirection_members[1] = {
+{
+ UA_TYPENAME("") /* .memberName */
+ UA_TYPES_INT32, /* .memberTypeIndex */
+ 0, /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+}};
+
+/* CallMethodRequest */
+static UA_DataTypeMember CallMethodRequest_members[3] = {
+{
+ UA_TYPENAME("objectId") /* .memberName */
+ UA_TYPES_NODEID, /* .memberTypeIndex */
+ 0, /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("methodId") /* .memberName */
+ UA_TYPES_NODEID, /* .memberTypeIndex */
+ offsetof(UA_CallMethodRequest, methodId) - offsetof(UA_CallMethodRequest, objectId) - sizeof(UA_NodeId), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("inputArguments") /* .memberName */
+ UA_TYPES_VARIANT, /* .memberTypeIndex */
+ offsetof(UA_CallMethodRequest, inputArgumentsSize) - offsetof(UA_CallMethodRequest, methodId) - sizeof(UA_NodeId), /* .padding */
+ true, /* .namespaceZero */
+ true /* .isArray */
+}};
+
+/* RedundancySupport */
+static UA_DataTypeMember RedundancySupport_members[1] = {
+{
+ UA_TYPENAME("") /* .memberName */
+ UA_TYPES_INT32, /* .memberTypeIndex */
+ 0, /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+}};
+
+/* EventNotificationList */
+static UA_DataTypeMember EventNotificationList_members[1] = {
+{
+ UA_TYPENAME("events") /* .memberName */
+ UA_TYPES_EVENTFIELDLIST, /* .memberTypeIndex */
+ 0, /* .padding */
+ true, /* .namespaceZero */
+ true /* .isArray */
+}};
+
+/* UnregisterNodesRequest */
+static UA_DataTypeMember UnregisterNodesRequest_members[2] = {
+{
+ UA_TYPENAME("requestHeader") /* .memberName */
+ UA_TYPES_REQUESTHEADER, /* .memberTypeIndex */
+ 0, /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("nodesToUnregister") /* .memberName */
+ UA_TYPES_NODEID, /* .memberTypeIndex */
+ offsetof(UA_UnregisterNodesRequest, nodesToUnregisterSize) - offsetof(UA_UnregisterNodesRequest, requestHeader) - sizeof(UA_RequestHeader), /* .padding */
+ true, /* .namespaceZero */
+ true /* .isArray */
+}};
+
+/* ContentFilterElementResult */
+static UA_DataTypeMember ContentFilterElementResult_members[3] = {
+{
+ UA_TYPENAME("statusCode") /* .memberName */
+ UA_TYPES_STATUSCODE, /* .memberTypeIndex */
+ 0, /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("operandStatusCodes") /* .memberName */
+ UA_TYPES_STATUSCODE, /* .memberTypeIndex */
+ offsetof(UA_ContentFilterElementResult, operandStatusCodesSize) - offsetof(UA_ContentFilterElementResult, statusCode) - sizeof(UA_StatusCode), /* .padding */
+ true, /* .namespaceZero */
+ true /* .isArray */
+},
+{
+ UA_TYPENAME("operandDiagnosticInfos") /* .memberName */
+ UA_TYPES_DIAGNOSTICINFO, /* .memberTypeIndex */
+ offsetof(UA_ContentFilterElementResult, operandDiagnosticInfosSize) - offsetof(UA_ContentFilterElementResult, operandStatusCodes) - sizeof(void*), /* .padding */
+ true, /* .namespaceZero */
+ true /* .isArray */
+}};
+
+/* SimpleAttributeOperand */
+static UA_DataTypeMember SimpleAttributeOperand_members[4] = {
+{
+ UA_TYPENAME("typeDefinitionId") /* .memberName */
+ UA_TYPES_NODEID, /* .memberTypeIndex */
+ 0, /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("browsePath") /* .memberName */
+ UA_TYPES_QUALIFIEDNAME, /* .memberTypeIndex */
+ offsetof(UA_SimpleAttributeOperand, browsePathSize) - offsetof(UA_SimpleAttributeOperand, typeDefinitionId) - sizeof(UA_NodeId), /* .padding */
+ true, /* .namespaceZero */
+ true /* .isArray */
+},
+{
+ UA_TYPENAME("attributeId") /* .memberName */
+ UA_TYPES_UINT32, /* .memberTypeIndex */
+ offsetof(UA_SimpleAttributeOperand, attributeId) - offsetof(UA_SimpleAttributeOperand, browsePath) - sizeof(void*), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("indexRange") /* .memberName */
+ UA_TYPES_STRING, /* .memberTypeIndex */
+ offsetof(UA_SimpleAttributeOperand, indexRange) - offsetof(UA_SimpleAttributeOperand, attributeId) - sizeof(UA_UInt32), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+}};
+
+/* LiteralOperand */
+static UA_DataTypeMember LiteralOperand_members[1] = {
+{
+ UA_TYPENAME("value") /* .memberName */
+ UA_TYPES_VARIANT, /* .memberTypeIndex */
+ 0, /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+}};
+
+/* QueryDataSet */
+static UA_DataTypeMember QueryDataSet_members[3] = {
+{
+ UA_TYPENAME("nodeId") /* .memberName */
+ UA_TYPES_EXPANDEDNODEID, /* .memberTypeIndex */
+ 0, /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("typeDefinitionNode") /* .memberName */
+ UA_TYPES_EXPANDEDNODEID, /* .memberTypeIndex */
+ offsetof(UA_QueryDataSet, typeDefinitionNode) - offsetof(UA_QueryDataSet, nodeId) - sizeof(UA_ExpandedNodeId), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("values") /* .memberName */
+ UA_TYPES_VARIANT, /* .memberTypeIndex */
+ offsetof(UA_QueryDataSet, valuesSize) - offsetof(UA_QueryDataSet, typeDefinitionNode) - sizeof(UA_ExpandedNodeId), /* .padding */
+ true, /* .namespaceZero */
+ true /* .isArray */
+}};
+
+/* AnonymousIdentityToken */
+static UA_DataTypeMember AnonymousIdentityToken_members[1] = {
+{
+ UA_TYPENAME("policyId") /* .memberName */
+ UA_TYPES_STRING, /* .memberTypeIndex */
+ 0, /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+}};
+
+/* SetPublishingModeRequest */
+static UA_DataTypeMember SetPublishingModeRequest_members[3] = {
+{
+ UA_TYPENAME("requestHeader") /* .memberName */
+ UA_TYPES_REQUESTHEADER, /* .memberTypeIndex */
+ 0, /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("publishingEnabled") /* .memberName */
+ UA_TYPES_BOOLEAN, /* .memberTypeIndex */
+ offsetof(UA_SetPublishingModeRequest, publishingEnabled) - offsetof(UA_SetPublishingModeRequest, requestHeader) - sizeof(UA_RequestHeader), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("subscriptionIds") /* .memberName */
+ UA_TYPES_UINT32, /* .memberTypeIndex */
+ offsetof(UA_SetPublishingModeRequest, subscriptionIdsSize) - offsetof(UA_SetPublishingModeRequest, publishingEnabled) - sizeof(UA_Boolean), /* .padding */
+ true, /* .namespaceZero */
+ true /* .isArray */
+}};
+
+/* MonitoredItemCreateResult */
+static UA_DataTypeMember MonitoredItemCreateResult_members[5] = {
+{
+ UA_TYPENAME("statusCode") /* .memberName */
+ UA_TYPES_STATUSCODE, /* .memberTypeIndex */
+ 0, /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("monitoredItemId") /* .memberName */
+ UA_TYPES_UINT32, /* .memberTypeIndex */
+ offsetof(UA_MonitoredItemCreateResult, monitoredItemId) - offsetof(UA_MonitoredItemCreateResult, statusCode) - sizeof(UA_StatusCode), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("revisedSamplingInterval") /* .memberName */
+ UA_TYPES_DOUBLE, /* .memberTypeIndex */
+ offsetof(UA_MonitoredItemCreateResult, revisedSamplingInterval) - offsetof(UA_MonitoredItemCreateResult, monitoredItemId) - sizeof(UA_UInt32), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("revisedQueueSize") /* .memberName */
+ UA_TYPES_UINT32, /* .memberTypeIndex */
+ offsetof(UA_MonitoredItemCreateResult, revisedQueueSize) - offsetof(UA_MonitoredItemCreateResult, revisedSamplingInterval) - sizeof(UA_Double), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("filterResult") /* .memberName */
+ UA_TYPES_EXTENSIONOBJECT, /* .memberTypeIndex */
+ offsetof(UA_MonitoredItemCreateResult, filterResult) - offsetof(UA_MonitoredItemCreateResult, revisedQueueSize) - sizeof(UA_UInt32), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+}};
+
+/* TimestampsToReturn */
+static UA_DataTypeMember TimestampsToReturn_members[1] = {
+{
+ UA_TYPENAME("") /* .memberName */
+ UA_TYPES_INT32, /* .memberTypeIndex */
+ 0, /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+}};
+
+/* CallRequest */
+static UA_DataTypeMember CallRequest_members[2] = {
+{
+ UA_TYPENAME("requestHeader") /* .memberName */
+ UA_TYPES_REQUESTHEADER, /* .memberTypeIndex */
+ 0, /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("methodsToCall") /* .memberName */
+ UA_TYPES_CALLMETHODREQUEST, /* .memberTypeIndex */
+ offsetof(UA_CallRequest, methodsToCallSize) - offsetof(UA_CallRequest, requestHeader) - sizeof(UA_RequestHeader), /* .padding */
+ true, /* .namespaceZero */
+ true /* .isArray */
+}};
+
+/* MethodAttributes */
+static UA_DataTypeMember MethodAttributes_members[7] = {
+{
+ UA_TYPENAME("specifiedAttributes") /* .memberName */
+ UA_TYPES_UINT32, /* .memberTypeIndex */
+ 0, /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("displayName") /* .memberName */
+ UA_TYPES_LOCALIZEDTEXT, /* .memberTypeIndex */
+ offsetof(UA_MethodAttributes, displayName) - offsetof(UA_MethodAttributes, specifiedAttributes) - sizeof(UA_UInt32), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("description") /* .memberName */
+ UA_TYPES_LOCALIZEDTEXT, /* .memberTypeIndex */
+ offsetof(UA_MethodAttributes, description) - offsetof(UA_MethodAttributes, displayName) - sizeof(UA_LocalizedText), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("writeMask") /* .memberName */
+ UA_TYPES_UINT32, /* .memberTypeIndex */
+ offsetof(UA_MethodAttributes, writeMask) - offsetof(UA_MethodAttributes, description) - sizeof(UA_LocalizedText), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("userWriteMask") /* .memberName */
+ UA_TYPES_UINT32, /* .memberTypeIndex */
+ offsetof(UA_MethodAttributes, userWriteMask) - offsetof(UA_MethodAttributes, writeMask) - sizeof(UA_UInt32), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("executable") /* .memberName */
+ UA_TYPES_BOOLEAN, /* .memberTypeIndex */
+ offsetof(UA_MethodAttributes, executable) - offsetof(UA_MethodAttributes, userWriteMask) - sizeof(UA_UInt32), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("userExecutable") /* .memberName */
+ UA_TYPES_BOOLEAN, /* .memberTypeIndex */
+ offsetof(UA_MethodAttributes, userExecutable) - offsetof(UA_MethodAttributes, executable) - sizeof(UA_Boolean), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+}};
+
+/* DeleteReferencesItem */
+static UA_DataTypeMember DeleteReferencesItem_members[5] = {
+{
+ UA_TYPENAME("sourceNodeId") /* .memberName */
+ UA_TYPES_NODEID, /* .memberTypeIndex */
+ 0, /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("referenceTypeId") /* .memberName */
+ UA_TYPES_NODEID, /* .memberTypeIndex */
+ offsetof(UA_DeleteReferencesItem, referenceTypeId) - offsetof(UA_DeleteReferencesItem, sourceNodeId) - sizeof(UA_NodeId), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("isForward") /* .memberName */
+ UA_TYPES_BOOLEAN, /* .memberTypeIndex */
+ offsetof(UA_DeleteReferencesItem, isForward) - offsetof(UA_DeleteReferencesItem, referenceTypeId) - sizeof(UA_NodeId), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("targetNodeId") /* .memberName */
+ UA_TYPES_EXPANDEDNODEID, /* .memberTypeIndex */
+ offsetof(UA_DeleteReferencesItem, targetNodeId) - offsetof(UA_DeleteReferencesItem, isForward) - sizeof(UA_Boolean), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("deleteBidirectional") /* .memberName */
+ UA_TYPES_BOOLEAN, /* .memberTypeIndex */
+ offsetof(UA_DeleteReferencesItem, deleteBidirectional) - offsetof(UA_DeleteReferencesItem, targetNodeId) - sizeof(UA_ExpandedNodeId), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+}};
+
+/* WriteValue */
+static UA_DataTypeMember WriteValue_members[4] = {
+{
+ UA_TYPENAME("nodeId") /* .memberName */
+ UA_TYPES_NODEID, /* .memberTypeIndex */
+ 0, /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("attributeId") /* .memberName */
+ UA_TYPES_UINT32, /* .memberTypeIndex */
+ offsetof(UA_WriteValue, attributeId) - offsetof(UA_WriteValue, nodeId) - sizeof(UA_NodeId), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("indexRange") /* .memberName */
+ UA_TYPES_STRING, /* .memberTypeIndex */
+ offsetof(UA_WriteValue, indexRange) - offsetof(UA_WriteValue, attributeId) - sizeof(UA_UInt32), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("value") /* .memberName */
+ UA_TYPES_DATAVALUE, /* .memberTypeIndex */
+ offsetof(UA_WriteValue, value) - offsetof(UA_WriteValue, indexRange) - sizeof(UA_String), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+}};
+
+/* NodeAttributesMask */
+static UA_DataTypeMember NodeAttributesMask_members[1] = {
+{
+ UA_TYPENAME("") /* .memberName */
+ UA_TYPES_INT32, /* .memberTypeIndex */
+ 0, /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+}};
+
+/* MessageSecurityMode */
+static UA_DataTypeMember MessageSecurityMode_members[1] = {
+{
+ UA_TYPENAME("") /* .memberName */
+ UA_TYPES_INT32, /* .memberTypeIndex */
+ 0, /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+}};
+
+/* MonitoringParameters */
+static UA_DataTypeMember MonitoringParameters_members[5] = {
+{
+ UA_TYPENAME("clientHandle") /* .memberName */
+ UA_TYPES_UINT32, /* .memberTypeIndex */
+ 0, /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("samplingInterval") /* .memberName */
+ UA_TYPES_DOUBLE, /* .memberTypeIndex */
+ offsetof(UA_MonitoringParameters, samplingInterval) - offsetof(UA_MonitoringParameters, clientHandle) - sizeof(UA_UInt32), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("filter") /* .memberName */
+ UA_TYPES_EXTENSIONOBJECT, /* .memberTypeIndex */
+ offsetof(UA_MonitoringParameters, filter) - offsetof(UA_MonitoringParameters, samplingInterval) - sizeof(UA_Double), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("queueSize") /* .memberName */
+ UA_TYPES_UINT32, /* .memberTypeIndex */
+ offsetof(UA_MonitoringParameters, queueSize) - offsetof(UA_MonitoringParameters, filter) - sizeof(UA_ExtensionObject), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("discardOldest") /* .memberName */
+ UA_TYPES_BOOLEAN, /* .memberTypeIndex */
+ offsetof(UA_MonitoringParameters, discardOldest) - offsetof(UA_MonitoringParameters, queueSize) - sizeof(UA_UInt32), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+}};
+
+/* ReferenceNode */
+static UA_DataTypeMember ReferenceNode_members[3] = {
+{
+ UA_TYPENAME("referenceTypeId") /* .memberName */
+ UA_TYPES_NODEID, /* .memberTypeIndex */
+ 0, /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("isInverse") /* .memberName */
+ UA_TYPES_BOOLEAN, /* .memberTypeIndex */
+ offsetof(UA_ReferenceNode, isInverse) - offsetof(UA_ReferenceNode, referenceTypeId) - sizeof(UA_NodeId), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("targetId") /* .memberName */
+ UA_TYPES_EXPANDEDNODEID, /* .memberTypeIndex */
+ offsetof(UA_ReferenceNode, targetId) - offsetof(UA_ReferenceNode, isInverse) - sizeof(UA_Boolean), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+}};
+
+/* Argument */
+static UA_DataTypeMember Argument_members[5] = {
+{
+ UA_TYPENAME("name") /* .memberName */
+ UA_TYPES_STRING, /* .memberTypeIndex */
+ 0, /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("dataType") /* .memberName */
+ UA_TYPES_NODEID, /* .memberTypeIndex */
+ offsetof(UA_Argument, dataType) - offsetof(UA_Argument, name) - sizeof(UA_String), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("valueRank") /* .memberName */
+ UA_TYPES_INT32, /* .memberTypeIndex */
+ offsetof(UA_Argument, valueRank) - offsetof(UA_Argument, dataType) - sizeof(UA_NodeId), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("arrayDimensions") /* .memberName */
+ UA_TYPES_UINT32, /* .memberTypeIndex */
+ offsetof(UA_Argument, arrayDimensionsSize) - offsetof(UA_Argument, valueRank) - sizeof(UA_Int32), /* .padding */
+ true, /* .namespaceZero */
+ true /* .isArray */
+},
+{
+ UA_TYPENAME("description") /* .memberName */
+ UA_TYPES_LOCALIZEDTEXT, /* .memberTypeIndex */
+ offsetof(UA_Argument, description) - offsetof(UA_Argument, arrayDimensions) - sizeof(void*), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+}};
+
+/* ChannelSecurityToken */
+static UA_DataTypeMember ChannelSecurityToken_members[4] = {
+{
+ UA_TYPENAME("channelId") /* .memberName */
+ UA_TYPES_UINT32, /* .memberTypeIndex */
+ 0, /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("tokenId") /* .memberName */
+ UA_TYPES_UINT32, /* .memberTypeIndex */
+ offsetof(UA_ChannelSecurityToken, tokenId) - offsetof(UA_ChannelSecurityToken, channelId) - sizeof(UA_UInt32), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("createdAt") /* .memberName */
+ UA_TYPES_DATETIME, /* .memberTypeIndex */
+ offsetof(UA_ChannelSecurityToken, createdAt) - offsetof(UA_ChannelSecurityToken, tokenId) - sizeof(UA_UInt32), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("revisedLifetime") /* .memberName */
+ UA_TYPES_UINT32, /* .memberTypeIndex */
+ offsetof(UA_ChannelSecurityToken, revisedLifetime) - offsetof(UA_ChannelSecurityToken, createdAt) - sizeof(UA_DateTime), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+}};
+
+/* UserIdentityToken */
+static UA_DataTypeMember UserIdentityToken_members[1] = {
+{
+ UA_TYPENAME("policyId") /* .memberName */
+ UA_TYPES_STRING, /* .memberTypeIndex */
+ 0, /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+}};
+
+/* SignatureData */
+static UA_DataTypeMember SignatureData_members[2] = {
+{
+ UA_TYPENAME("algorithm") /* .memberName */
+ UA_TYPES_STRING, /* .memberTypeIndex */
+ 0, /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("signature") /* .memberName */
+ UA_TYPES_BYTESTRING, /* .memberTypeIndex */
+ offsetof(UA_SignatureData, signature) - offsetof(UA_SignatureData, algorithm) - sizeof(UA_String), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+}};
+
+/* ObjectTypeAttributes */
+static UA_DataTypeMember ObjectTypeAttributes_members[6] = {
+{
+ UA_TYPENAME("specifiedAttributes") /* .memberName */
+ UA_TYPES_UINT32, /* .memberTypeIndex */
+ 0, /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("displayName") /* .memberName */
+ UA_TYPES_LOCALIZEDTEXT, /* .memberTypeIndex */
+ offsetof(UA_ObjectTypeAttributes, displayName) - offsetof(UA_ObjectTypeAttributes, specifiedAttributes) - sizeof(UA_UInt32), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("description") /* .memberName */
+ UA_TYPES_LOCALIZEDTEXT, /* .memberTypeIndex */
+ offsetof(UA_ObjectTypeAttributes, description) - offsetof(UA_ObjectTypeAttributes, displayName) - sizeof(UA_LocalizedText), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("writeMask") /* .memberName */
+ UA_TYPES_UINT32, /* .memberTypeIndex */
+ offsetof(UA_ObjectTypeAttributes, writeMask) - offsetof(UA_ObjectTypeAttributes, description) - sizeof(UA_LocalizedText), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("userWriteMask") /* .memberName */
+ UA_TYPES_UINT32, /* .memberTypeIndex */
+ offsetof(UA_ObjectTypeAttributes, userWriteMask) - offsetof(UA_ObjectTypeAttributes, writeMask) - sizeof(UA_UInt32), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("isAbstract") /* .memberName */
+ UA_TYPES_BOOLEAN, /* .memberTypeIndex */
+ offsetof(UA_ObjectTypeAttributes, isAbstract) - offsetof(UA_ObjectTypeAttributes, userWriteMask) - sizeof(UA_UInt32), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+}};
+
+/* DeadbandType */
+static UA_DataTypeMember DeadbandType_members[1] = {
+{
+ UA_TYPENAME("") /* .memberName */
+ UA_TYPES_INT32, /* .memberTypeIndex */
+ 0, /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+}};
+
+/* SecurityTokenRequestType */
+static UA_DataTypeMember SecurityTokenRequestType_members[1] = {
+{
+ UA_TYPENAME("") /* .memberName */
+ UA_TYPES_INT32, /* .memberTypeIndex */
+ 0, /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+}};
+
+/* NodeAttributes */
+static UA_DataTypeMember NodeAttributes_members[5] = {
+{
+ UA_TYPENAME("specifiedAttributes") /* .memberName */
+ UA_TYPES_UINT32, /* .memberTypeIndex */
+ 0, /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("displayName") /* .memberName */
+ UA_TYPES_LOCALIZEDTEXT, /* .memberTypeIndex */
+ offsetof(UA_NodeAttributes, displayName) - offsetof(UA_NodeAttributes, specifiedAttributes) - sizeof(UA_UInt32), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("description") /* .memberName */
+ UA_TYPES_LOCALIZEDTEXT, /* .memberTypeIndex */
+ offsetof(UA_NodeAttributes, description) - offsetof(UA_NodeAttributes, displayName) - sizeof(UA_LocalizedText), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("writeMask") /* .memberName */
+ UA_TYPES_UINT32, /* .memberTypeIndex */
+ offsetof(UA_NodeAttributes, writeMask) - offsetof(UA_NodeAttributes, description) - sizeof(UA_LocalizedText), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("userWriteMask") /* .memberName */
+ UA_TYPES_UINT32, /* .memberTypeIndex */
+ offsetof(UA_NodeAttributes, userWriteMask) - offsetof(UA_NodeAttributes, writeMask) - sizeof(UA_UInt32), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+}};
+
+/* DataChangeTrigger */
+static UA_DataTypeMember DataChangeTrigger_members[1] = {
+{
+ UA_TYPENAME("") /* .memberName */
+ UA_TYPES_INT32, /* .memberTypeIndex */
+ 0, /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+}};
+
+/* BuildInfo */
+static UA_DataTypeMember BuildInfo_members[6] = {
+{
+ UA_TYPENAME("productUri") /* .memberName */
+ UA_TYPES_STRING, /* .memberTypeIndex */
+ 0, /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("manufacturerName") /* .memberName */
+ UA_TYPES_STRING, /* .memberTypeIndex */
+ offsetof(UA_BuildInfo, manufacturerName) - offsetof(UA_BuildInfo, productUri) - sizeof(UA_String), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("productName") /* .memberName */
+ UA_TYPES_STRING, /* .memberTypeIndex */
+ offsetof(UA_BuildInfo, productName) - offsetof(UA_BuildInfo, manufacturerName) - sizeof(UA_String), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("softwareVersion") /* .memberName */
+ UA_TYPES_STRING, /* .memberTypeIndex */
+ offsetof(UA_BuildInfo, softwareVersion) - offsetof(UA_BuildInfo, productName) - sizeof(UA_String), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("buildNumber") /* .memberName */
+ UA_TYPES_STRING, /* .memberTypeIndex */
+ offsetof(UA_BuildInfo, buildNumber) - offsetof(UA_BuildInfo, softwareVersion) - sizeof(UA_String), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("buildDate") /* .memberName */
+ UA_TYPES_DATETIME, /* .memberTypeIndex */
+ offsetof(UA_BuildInfo, buildDate) - offsetof(UA_BuildInfo, buildNumber) - sizeof(UA_String), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+}};
+
+/* NodeClass */
+static UA_DataTypeMember NodeClass_members[1] = {
+{
+ UA_TYPENAME("") /* .memberName */
+ UA_TYPES_INT32, /* .memberTypeIndex */
+ 0, /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+}};
+
+/* SubscriptionDiagnosticsDataType */
+static UA_DataTypeMember SubscriptionDiagnosticsDataType_members[31] = {
+{
+ UA_TYPENAME("sessionId") /* .memberName */
+ UA_TYPES_NODEID, /* .memberTypeIndex */
+ 0, /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("subscriptionId") /* .memberName */
+ UA_TYPES_UINT32, /* .memberTypeIndex */
+ offsetof(UA_SubscriptionDiagnosticsDataType, subscriptionId) - offsetof(UA_SubscriptionDiagnosticsDataType, sessionId) - sizeof(UA_NodeId), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("priority") /* .memberName */
+ UA_TYPES_BYTE, /* .memberTypeIndex */
+ offsetof(UA_SubscriptionDiagnosticsDataType, priority) - offsetof(UA_SubscriptionDiagnosticsDataType, subscriptionId) - sizeof(UA_UInt32), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("publishingInterval") /* .memberName */
+ UA_TYPES_DOUBLE, /* .memberTypeIndex */
+ offsetof(UA_SubscriptionDiagnosticsDataType, publishingInterval) - offsetof(UA_SubscriptionDiagnosticsDataType, priority) - sizeof(UA_Byte), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("maxKeepAliveCount") /* .memberName */
+ UA_TYPES_UINT32, /* .memberTypeIndex */
+ offsetof(UA_SubscriptionDiagnosticsDataType, maxKeepAliveCount) - offsetof(UA_SubscriptionDiagnosticsDataType, publishingInterval) - sizeof(UA_Double), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("maxLifetimeCount") /* .memberName */
+ UA_TYPES_UINT32, /* .memberTypeIndex */
+ offsetof(UA_SubscriptionDiagnosticsDataType, maxLifetimeCount) - offsetof(UA_SubscriptionDiagnosticsDataType, maxKeepAliveCount) - sizeof(UA_UInt32), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("maxNotificationsPerPublish") /* .memberName */
+ UA_TYPES_UINT32, /* .memberTypeIndex */
+ offsetof(UA_SubscriptionDiagnosticsDataType, maxNotificationsPerPublish) - offsetof(UA_SubscriptionDiagnosticsDataType, maxLifetimeCount) - sizeof(UA_UInt32), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("publishingEnabled") /* .memberName */
+ UA_TYPES_BOOLEAN, /* .memberTypeIndex */
+ offsetof(UA_SubscriptionDiagnosticsDataType, publishingEnabled) - offsetof(UA_SubscriptionDiagnosticsDataType, maxNotificationsPerPublish) - sizeof(UA_UInt32), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("modifyCount") /* .memberName */
+ UA_TYPES_UINT32, /* .memberTypeIndex */
+ offsetof(UA_SubscriptionDiagnosticsDataType, modifyCount) - offsetof(UA_SubscriptionDiagnosticsDataType, publishingEnabled) - sizeof(UA_Boolean), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("enableCount") /* .memberName */
+ UA_TYPES_UINT32, /* .memberTypeIndex */
+ offsetof(UA_SubscriptionDiagnosticsDataType, enableCount) - offsetof(UA_SubscriptionDiagnosticsDataType, modifyCount) - sizeof(UA_UInt32), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("disableCount") /* .memberName */
+ UA_TYPES_UINT32, /* .memberTypeIndex */
+ offsetof(UA_SubscriptionDiagnosticsDataType, disableCount) - offsetof(UA_SubscriptionDiagnosticsDataType, enableCount) - sizeof(UA_UInt32), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("republishRequestCount") /* .memberName */
+ UA_TYPES_UINT32, /* .memberTypeIndex */
+ offsetof(UA_SubscriptionDiagnosticsDataType, republishRequestCount) - offsetof(UA_SubscriptionDiagnosticsDataType, disableCount) - sizeof(UA_UInt32), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("republishMessageRequestCount") /* .memberName */
+ UA_TYPES_UINT32, /* .memberTypeIndex */
+ offsetof(UA_SubscriptionDiagnosticsDataType, republishMessageRequestCount) - offsetof(UA_SubscriptionDiagnosticsDataType, republishRequestCount) - sizeof(UA_UInt32), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("republishMessageCount") /* .memberName */
+ UA_TYPES_UINT32, /* .memberTypeIndex */
+ offsetof(UA_SubscriptionDiagnosticsDataType, republishMessageCount) - offsetof(UA_SubscriptionDiagnosticsDataType, republishMessageRequestCount) - sizeof(UA_UInt32), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("transferRequestCount") /* .memberName */
+ UA_TYPES_UINT32, /* .memberTypeIndex */
+ offsetof(UA_SubscriptionDiagnosticsDataType, transferRequestCount) - offsetof(UA_SubscriptionDiagnosticsDataType, republishMessageCount) - sizeof(UA_UInt32), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("transferredToAltClientCount") /* .memberName */
+ UA_TYPES_UINT32, /* .memberTypeIndex */
+ offsetof(UA_SubscriptionDiagnosticsDataType, transferredToAltClientCount) - offsetof(UA_SubscriptionDiagnosticsDataType, transferRequestCount) - sizeof(UA_UInt32), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("transferredToSameClientCount") /* .memberName */
+ UA_TYPES_UINT32, /* .memberTypeIndex */
+ offsetof(UA_SubscriptionDiagnosticsDataType, transferredToSameClientCount) - offsetof(UA_SubscriptionDiagnosticsDataType, transferredToAltClientCount) - sizeof(UA_UInt32), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("publishRequestCount") /* .memberName */
+ UA_TYPES_UINT32, /* .memberTypeIndex */
+ offsetof(UA_SubscriptionDiagnosticsDataType, publishRequestCount) - offsetof(UA_SubscriptionDiagnosticsDataType, transferredToSameClientCount) - sizeof(UA_UInt32), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("dataChangeNotificationsCount") /* .memberName */
+ UA_TYPES_UINT32, /* .memberTypeIndex */
+ offsetof(UA_SubscriptionDiagnosticsDataType, dataChangeNotificationsCount) - offsetof(UA_SubscriptionDiagnosticsDataType, publishRequestCount) - sizeof(UA_UInt32), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("eventNotificationsCount") /* .memberName */
+ UA_TYPES_UINT32, /* .memberTypeIndex */
+ offsetof(UA_SubscriptionDiagnosticsDataType, eventNotificationsCount) - offsetof(UA_SubscriptionDiagnosticsDataType, dataChangeNotificationsCount) - sizeof(UA_UInt32), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("notificationsCount") /* .memberName */
+ UA_TYPES_UINT32, /* .memberTypeIndex */
+ offsetof(UA_SubscriptionDiagnosticsDataType, notificationsCount) - offsetof(UA_SubscriptionDiagnosticsDataType, eventNotificationsCount) - sizeof(UA_UInt32), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("latePublishRequestCount") /* .memberName */
+ UA_TYPES_UINT32, /* .memberTypeIndex */
+ offsetof(UA_SubscriptionDiagnosticsDataType, latePublishRequestCount) - offsetof(UA_SubscriptionDiagnosticsDataType, notificationsCount) - sizeof(UA_UInt32), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("currentKeepAliveCount") /* .memberName */
+ UA_TYPES_UINT32, /* .memberTypeIndex */
+ offsetof(UA_SubscriptionDiagnosticsDataType, currentKeepAliveCount) - offsetof(UA_SubscriptionDiagnosticsDataType, latePublishRequestCount) - sizeof(UA_UInt32), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("currentLifetimeCount") /* .memberName */
+ UA_TYPES_UINT32, /* .memberTypeIndex */
+ offsetof(UA_SubscriptionDiagnosticsDataType, currentLifetimeCount) - offsetof(UA_SubscriptionDiagnosticsDataType, currentKeepAliveCount) - sizeof(UA_UInt32), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("unacknowledgedMessageCount") /* .memberName */
+ UA_TYPES_UINT32, /* .memberTypeIndex */
+ offsetof(UA_SubscriptionDiagnosticsDataType, unacknowledgedMessageCount) - offsetof(UA_SubscriptionDiagnosticsDataType, currentLifetimeCount) - sizeof(UA_UInt32), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("discardedMessageCount") /* .memberName */
+ UA_TYPES_UINT32, /* .memberTypeIndex */
+ offsetof(UA_SubscriptionDiagnosticsDataType, discardedMessageCount) - offsetof(UA_SubscriptionDiagnosticsDataType, unacknowledgedMessageCount) - sizeof(UA_UInt32), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("monitoredItemCount") /* .memberName */
+ UA_TYPES_UINT32, /* .memberTypeIndex */
+ offsetof(UA_SubscriptionDiagnosticsDataType, monitoredItemCount) - offsetof(UA_SubscriptionDiagnosticsDataType, discardedMessageCount) - sizeof(UA_UInt32), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("disabledMonitoredItemCount") /* .memberName */
+ UA_TYPES_UINT32, /* .memberTypeIndex */
+ offsetof(UA_SubscriptionDiagnosticsDataType, disabledMonitoredItemCount) - offsetof(UA_SubscriptionDiagnosticsDataType, monitoredItemCount) - sizeof(UA_UInt32), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("monitoringQueueOverflowCount") /* .memberName */
+ UA_TYPES_UINT32, /* .memberTypeIndex */
+ offsetof(UA_SubscriptionDiagnosticsDataType, monitoringQueueOverflowCount) - offsetof(UA_SubscriptionDiagnosticsDataType, disabledMonitoredItemCount) - sizeof(UA_UInt32), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("nextSequenceNumber") /* .memberName */
+ UA_TYPES_UINT32, /* .memberTypeIndex */
+ offsetof(UA_SubscriptionDiagnosticsDataType, nextSequenceNumber) - offsetof(UA_SubscriptionDiagnosticsDataType, monitoringQueueOverflowCount) - sizeof(UA_UInt32), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("eventQueueOverFlowCount") /* .memberName */
+ UA_TYPES_UINT32, /* .memberTypeIndex */
+ offsetof(UA_SubscriptionDiagnosticsDataType, eventQueueOverFlowCount) - offsetof(UA_SubscriptionDiagnosticsDataType, nextSequenceNumber) - sizeof(UA_UInt32), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+}};
+
+/* FilterOperand */
+#define FilterOperand_members NULL
+
+/* MonitoredItemNotification */
+static UA_DataTypeMember MonitoredItemNotification_members[2] = {
+{
+ UA_TYPENAME("clientHandle") /* .memberName */
+ UA_TYPES_UINT32, /* .memberTypeIndex */
+ 0, /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("value") /* .memberName */
+ UA_TYPES_DATAVALUE, /* .memberTypeIndex */
+ offsetof(UA_MonitoredItemNotification, value) - offsetof(UA_MonitoredItemNotification, clientHandle) - sizeof(UA_UInt32), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+}};
+
+/* DeleteNodesItem */
+static UA_DataTypeMember DeleteNodesItem_members[2] = {
+{
+ UA_TYPENAME("nodeId") /* .memberName */
+ UA_TYPES_NODEID, /* .memberTypeIndex */
+ 0, /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("deleteTargetReferences") /* .memberName */
+ UA_TYPES_BOOLEAN, /* .memberTypeIndex */
+ offsetof(UA_DeleteNodesItem, deleteTargetReferences) - offsetof(UA_DeleteNodesItem, nodeId) - sizeof(UA_NodeId), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+}};
+
+/* DeleteSubscriptionsRequest */
+static UA_DataTypeMember DeleteSubscriptionsRequest_members[2] = {
+{
+ UA_TYPENAME("requestHeader") /* .memberName */
+ UA_TYPES_REQUESTHEADER, /* .memberTypeIndex */
+ 0, /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("subscriptionIds") /* .memberName */
+ UA_TYPES_UINT32, /* .memberTypeIndex */
+ offsetof(UA_DeleteSubscriptionsRequest, subscriptionIdsSize) - offsetof(UA_DeleteSubscriptionsRequest, requestHeader) - sizeof(UA_RequestHeader), /* .padding */
+ true, /* .namespaceZero */
+ true /* .isArray */
+}};
+
+/* SubscriptionAcknowledgement */
+static UA_DataTypeMember SubscriptionAcknowledgement_members[2] = {
+{
+ UA_TYPENAME("subscriptionId") /* .memberName */
+ UA_TYPES_UINT32, /* .memberTypeIndex */
+ 0, /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("sequenceNumber") /* .memberName */
+ UA_TYPES_UINT32, /* .memberTypeIndex */
+ offsetof(UA_SubscriptionAcknowledgement, sequenceNumber) - offsetof(UA_SubscriptionAcknowledgement, subscriptionId) - sizeof(UA_UInt32), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+}};
+
+/* ReadValueId */
+static UA_DataTypeMember ReadValueId_members[4] = {
+{
+ UA_TYPENAME("nodeId") /* .memberName */
+ UA_TYPES_NODEID, /* .memberTypeIndex */
+ 0, /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("attributeId") /* .memberName */
+ UA_TYPES_UINT32, /* .memberTypeIndex */
+ offsetof(UA_ReadValueId, attributeId) - offsetof(UA_ReadValueId, nodeId) - sizeof(UA_NodeId), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("indexRange") /* .memberName */
+ UA_TYPES_STRING, /* .memberTypeIndex */
+ offsetof(UA_ReadValueId, indexRange) - offsetof(UA_ReadValueId, attributeId) - sizeof(UA_UInt32), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("dataEncoding") /* .memberName */
+ UA_TYPES_QUALIFIEDNAME, /* .memberTypeIndex */
+ offsetof(UA_ReadValueId, dataEncoding) - offsetof(UA_ReadValueId, indexRange) - sizeof(UA_String), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+}};
+
+/* DataTypeAttributes */
+static UA_DataTypeMember DataTypeAttributes_members[6] = {
+{
+ UA_TYPENAME("specifiedAttributes") /* .memberName */
+ UA_TYPES_UINT32, /* .memberTypeIndex */
+ 0, /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("displayName") /* .memberName */
+ UA_TYPES_LOCALIZEDTEXT, /* .memberTypeIndex */
+ offsetof(UA_DataTypeAttributes, displayName) - offsetof(UA_DataTypeAttributes, specifiedAttributes) - sizeof(UA_UInt32), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("description") /* .memberName */
+ UA_TYPES_LOCALIZEDTEXT, /* .memberTypeIndex */
+ offsetof(UA_DataTypeAttributes, description) - offsetof(UA_DataTypeAttributes, displayName) - sizeof(UA_LocalizedText), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("writeMask") /* .memberName */
+ UA_TYPES_UINT32, /* .memberTypeIndex */
+ offsetof(UA_DataTypeAttributes, writeMask) - offsetof(UA_DataTypeAttributes, description) - sizeof(UA_LocalizedText), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("userWriteMask") /* .memberName */
+ UA_TYPES_UINT32, /* .memberTypeIndex */
+ offsetof(UA_DataTypeAttributes, userWriteMask) - offsetof(UA_DataTypeAttributes, writeMask) - sizeof(UA_UInt32), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("isAbstract") /* .memberName */
+ UA_TYPES_BOOLEAN, /* .memberTypeIndex */
+ offsetof(UA_DataTypeAttributes, isAbstract) - offsetof(UA_DataTypeAttributes, userWriteMask) - sizeof(UA_UInt32), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+}};
+
+/* ResponseHeader */
+static UA_DataTypeMember ResponseHeader_members[6] = {
+{
+ UA_TYPENAME("timestamp") /* .memberName */
+ UA_TYPES_DATETIME, /* .memberTypeIndex */
+ 0, /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("requestHandle") /* .memberName */
+ UA_TYPES_UINT32, /* .memberTypeIndex */
+ offsetof(UA_ResponseHeader, requestHandle) - offsetof(UA_ResponseHeader, timestamp) - sizeof(UA_DateTime), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("serviceResult") /* .memberName */
+ UA_TYPES_STATUSCODE, /* .memberTypeIndex */
+ offsetof(UA_ResponseHeader, serviceResult) - offsetof(UA_ResponseHeader, requestHandle) - sizeof(UA_UInt32), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("serviceDiagnostics") /* .memberName */
+ UA_TYPES_DIAGNOSTICINFO, /* .memberTypeIndex */
+ offsetof(UA_ResponseHeader, serviceDiagnostics) - offsetof(UA_ResponseHeader, serviceResult) - sizeof(UA_StatusCode), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("stringTable") /* .memberName */
+ UA_TYPES_STRING, /* .memberTypeIndex */
+ offsetof(UA_ResponseHeader, stringTableSize) - offsetof(UA_ResponseHeader, serviceDiagnostics) - sizeof(UA_DiagnosticInfo), /* .padding */
+ true, /* .namespaceZero */
+ true /* .isArray */
+},
+{
+ UA_TYPENAME("additionalHeader") /* .memberName */
+ UA_TYPES_EXTENSIONOBJECT, /* .memberTypeIndex */
+ offsetof(UA_ResponseHeader, additionalHeader) - offsetof(UA_ResponseHeader, stringTable) - sizeof(void*), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+}};
+
+/* DeleteMonitoredItemsRequest */
+static UA_DataTypeMember DeleteMonitoredItemsRequest_members[3] = {
+{
+ UA_TYPENAME("requestHeader") /* .memberName */
+ UA_TYPES_REQUESTHEADER, /* .memberTypeIndex */
+ 0, /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("subscriptionId") /* .memberName */
+ UA_TYPES_UINT32, /* .memberTypeIndex */
+ offsetof(UA_DeleteMonitoredItemsRequest, subscriptionId) - offsetof(UA_DeleteMonitoredItemsRequest, requestHeader) - sizeof(UA_RequestHeader), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("monitoredItemIds") /* .memberName */
+ UA_TYPES_UINT32, /* .memberTypeIndex */
+ offsetof(UA_DeleteMonitoredItemsRequest, monitoredItemIdsSize) - offsetof(UA_DeleteMonitoredItemsRequest, subscriptionId) - sizeof(UA_UInt32), /* .padding */
+ true, /* .namespaceZero */
+ true /* .isArray */
+}};
+
+/* ViewDescription */
+static UA_DataTypeMember ViewDescription_members[3] = {
+{
+ UA_TYPENAME("viewId") /* .memberName */
+ UA_TYPES_NODEID, /* .memberTypeIndex */
+ 0, /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("timestamp") /* .memberName */
+ UA_TYPES_DATETIME, /* .memberTypeIndex */
+ offsetof(UA_ViewDescription, timestamp) - offsetof(UA_ViewDescription, viewId) - sizeof(UA_NodeId), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("viewVersion") /* .memberName */
+ UA_TYPES_UINT32, /* .memberTypeIndex */
+ offsetof(UA_ViewDescription, viewVersion) - offsetof(UA_ViewDescription, timestamp) - sizeof(UA_DateTime), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+}};
+
+/* ServerOnNetwork */
+static UA_DataTypeMember ServerOnNetwork_members[4] = {
+{
+ UA_TYPENAME("recordId") /* .memberName */
+ UA_TYPES_UINT32, /* .memberTypeIndex */
+ 0, /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("serverName") /* .memberName */
+ UA_TYPES_STRING, /* .memberTypeIndex */
+ offsetof(UA_ServerOnNetwork, serverName) - offsetof(UA_ServerOnNetwork, recordId) - sizeof(UA_UInt32), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("discoveryUrl") /* .memberName */
+ UA_TYPES_STRING, /* .memberTypeIndex */
+ offsetof(UA_ServerOnNetwork, discoveryUrl) - offsetof(UA_ServerOnNetwork, serverName) - sizeof(UA_String), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("serverCapabilities") /* .memberName */
+ UA_TYPES_STRING, /* .memberTypeIndex */
+ offsetof(UA_ServerOnNetwork, serverCapabilitiesSize) - offsetof(UA_ServerOnNetwork, discoveryUrl) - sizeof(UA_String), /* .padding */
+ true, /* .namespaceZero */
+ true /* .isArray */
+}};
+
+/* DeleteMonitoredItemsResponse */
+static UA_DataTypeMember DeleteMonitoredItemsResponse_members[3] = {
+{
+ UA_TYPENAME("responseHeader") /* .memberName */
+ UA_TYPES_RESPONSEHEADER, /* .memberTypeIndex */
+ 0, /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("results") /* .memberName */
+ UA_TYPES_STATUSCODE, /* .memberTypeIndex */
+ offsetof(UA_DeleteMonitoredItemsResponse, resultsSize) - offsetof(UA_DeleteMonitoredItemsResponse, responseHeader) - sizeof(UA_ResponseHeader), /* .padding */
+ true, /* .namespaceZero */
+ true /* .isArray */
+},
+{
+ UA_TYPENAME("diagnosticInfos") /* .memberName */
+ UA_TYPES_DIAGNOSTICINFO, /* .memberTypeIndex */
+ offsetof(UA_DeleteMonitoredItemsResponse, diagnosticInfosSize) - offsetof(UA_DeleteMonitoredItemsResponse, results) - sizeof(void*), /* .padding */
+ true, /* .namespaceZero */
+ true /* .isArray */
+}};
+
+/* FindServersOnNetworkResponse */
+static UA_DataTypeMember FindServersOnNetworkResponse_members[3] = {
+{
+ UA_TYPENAME("responseHeader") /* .memberName */
+ UA_TYPES_RESPONSEHEADER, /* .memberTypeIndex */
+ 0, /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("lastCounterResetTime") /* .memberName */
+ UA_TYPES_DATETIME, /* .memberTypeIndex */
+ offsetof(UA_FindServersOnNetworkResponse, lastCounterResetTime) - offsetof(UA_FindServersOnNetworkResponse, responseHeader) - sizeof(UA_ResponseHeader), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("servers") /* .memberName */
+ UA_TYPES_SERVERONNETWORK, /* .memberTypeIndex */
+ offsetof(UA_FindServersOnNetworkResponse, serversSize) - offsetof(UA_FindServersOnNetworkResponse, lastCounterResetTime) - sizeof(UA_DateTime), /* .padding */
+ true, /* .namespaceZero */
+ true /* .isArray */
+}};
+
+/* RelativePath */
+static UA_DataTypeMember RelativePath_members[1] = {
+{
+ UA_TYPENAME("elements") /* .memberName */
+ UA_TYPES_RELATIVEPATHELEMENT, /* .memberTypeIndex */
+ 0, /* .padding */
+ true, /* .namespaceZero */
+ true /* .isArray */
+}};
+
+/* RegisterNodesRequest */
+static UA_DataTypeMember RegisterNodesRequest_members[2] = {
+{
+ UA_TYPENAME("requestHeader") /* .memberName */
+ UA_TYPES_REQUESTHEADER, /* .memberTypeIndex */
+ 0, /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("nodesToRegister") /* .memberName */
+ UA_TYPES_NODEID, /* .memberTypeIndex */
+ offsetof(UA_RegisterNodesRequest, nodesToRegisterSize) - offsetof(UA_RegisterNodesRequest, requestHeader) - sizeof(UA_RequestHeader), /* .padding */
+ true, /* .namespaceZero */
+ true /* .isArray */
+}};
+
+/* AggregateConfiguration */
+static UA_DataTypeMember AggregateConfiguration_members[5] = {
+{
+ UA_TYPENAME("useServerCapabilitiesDefaults") /* .memberName */
+ UA_TYPES_BOOLEAN, /* .memberTypeIndex */
+ 0, /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("treatUncertainAsBad") /* .memberName */
+ UA_TYPES_BOOLEAN, /* .memberTypeIndex */
+ offsetof(UA_AggregateConfiguration, treatUncertainAsBad) - offsetof(UA_AggregateConfiguration, useServerCapabilitiesDefaults) - sizeof(UA_Boolean), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("percentDataBad") /* .memberName */
+ UA_TYPES_BYTE, /* .memberTypeIndex */
+ offsetof(UA_AggregateConfiguration, percentDataBad) - offsetof(UA_AggregateConfiguration, treatUncertainAsBad) - sizeof(UA_Boolean), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("percentDataGood") /* .memberName */
+ UA_TYPES_BYTE, /* .memberTypeIndex */
+ offsetof(UA_AggregateConfiguration, percentDataGood) - offsetof(UA_AggregateConfiguration, percentDataBad) - sizeof(UA_Byte), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("useSlopedExtrapolation") /* .memberName */
+ UA_TYPES_BOOLEAN, /* .memberTypeIndex */
+ offsetof(UA_AggregateConfiguration, useSlopedExtrapolation) - offsetof(UA_AggregateConfiguration, percentDataGood) - sizeof(UA_Byte), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+}};
+
+/* DeleteNodesRequest */
+static UA_DataTypeMember DeleteNodesRequest_members[2] = {
+{
+ UA_TYPENAME("requestHeader") /* .memberName */
+ UA_TYPES_REQUESTHEADER, /* .memberTypeIndex */
+ 0, /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("nodesToDelete") /* .memberName */
+ UA_TYPES_DELETENODESITEM, /* .memberTypeIndex */
+ offsetof(UA_DeleteNodesRequest, nodesToDeleteSize) - offsetof(UA_DeleteNodesRequest, requestHeader) - sizeof(UA_RequestHeader), /* .padding */
+ true, /* .namespaceZero */
+ true /* .isArray */
+}};
+
+/* PublishResponse */
+static UA_DataTypeMember PublishResponse_members[7] = {
+{
+ UA_TYPENAME("responseHeader") /* .memberName */
+ UA_TYPES_RESPONSEHEADER, /* .memberTypeIndex */
+ 0, /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("subscriptionId") /* .memberName */
+ UA_TYPES_UINT32, /* .memberTypeIndex */
+ offsetof(UA_PublishResponse, subscriptionId) - offsetof(UA_PublishResponse, responseHeader) - sizeof(UA_ResponseHeader), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("availableSequenceNumbers") /* .memberName */
+ UA_TYPES_UINT32, /* .memberTypeIndex */
+ offsetof(UA_PublishResponse, availableSequenceNumbersSize) - offsetof(UA_PublishResponse, subscriptionId) - sizeof(UA_UInt32), /* .padding */
+ true, /* .namespaceZero */
+ true /* .isArray */
+},
+{
+ UA_TYPENAME("moreNotifications") /* .memberName */
+ UA_TYPES_BOOLEAN, /* .memberTypeIndex */
+ offsetof(UA_PublishResponse, moreNotifications) - offsetof(UA_PublishResponse, availableSequenceNumbers) - sizeof(void*), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("notificationMessage") /* .memberName */
+ UA_TYPES_NOTIFICATIONMESSAGE, /* .memberTypeIndex */
+ offsetof(UA_PublishResponse, notificationMessage) - offsetof(UA_PublishResponse, moreNotifications) - sizeof(UA_Boolean), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("results") /* .memberName */
+ UA_TYPES_STATUSCODE, /* .memberTypeIndex */
+ offsetof(UA_PublishResponse, resultsSize) - offsetof(UA_PublishResponse, notificationMessage) - sizeof(UA_NotificationMessage), /* .padding */
+ true, /* .namespaceZero */
+ true /* .isArray */
+},
+{
+ UA_TYPENAME("diagnosticInfos") /* .memberName */
+ UA_TYPES_DIAGNOSTICINFO, /* .memberTypeIndex */
+ offsetof(UA_PublishResponse, diagnosticInfosSize) - offsetof(UA_PublishResponse, results) - sizeof(void*), /* .padding */
+ true, /* .namespaceZero */
+ true /* .isArray */
+}};
+
+/* MonitoredItemModifyRequest */
+static UA_DataTypeMember MonitoredItemModifyRequest_members[2] = {
+{
+ UA_TYPENAME("monitoredItemId") /* .memberName */
+ UA_TYPES_UINT32, /* .memberTypeIndex */
+ 0, /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("requestedParameters") /* .memberName */
+ UA_TYPES_MONITORINGPARAMETERS, /* .memberTypeIndex */
+ offsetof(UA_MonitoredItemModifyRequest, requestedParameters) - offsetof(UA_MonitoredItemModifyRequest, monitoredItemId) - sizeof(UA_UInt32), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+}};
+
+/* ServiceCounterDataType */
+static UA_DataTypeMember ServiceCounterDataType_members[2] = {
+{
+ UA_TYPENAME("totalCount") /* .memberName */
+ UA_TYPES_UINT32, /* .memberTypeIndex */
+ 0, /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("errorCount") /* .memberName */
+ UA_TYPES_UINT32, /* .memberTypeIndex */
+ offsetof(UA_ServiceCounterDataType, errorCount) - offsetof(UA_ServiceCounterDataType, totalCount) - sizeof(UA_UInt32), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+}};
+
+/* ModelChangeStructureDataType */
+static UA_DataTypeMember ModelChangeStructureDataType_members[3] = {
+{
+ UA_TYPENAME("affected") /* .memberName */
+ UA_TYPES_NODEID, /* .memberTypeIndex */
+ 0, /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("affectedType") /* .memberName */
+ UA_TYPES_NODEID, /* .memberTypeIndex */
+ offsetof(UA_ModelChangeStructureDataType, affectedType) - offsetof(UA_ModelChangeStructureDataType, affected) - sizeof(UA_NodeId), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("verb") /* .memberName */
+ UA_TYPES_BYTE, /* .memberTypeIndex */
+ offsetof(UA_ModelChangeStructureDataType, verb) - offsetof(UA_ModelChangeStructureDataType, affectedType) - sizeof(UA_NodeId), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+}};
+
+/* UserNameIdentityToken */
+static UA_DataTypeMember UserNameIdentityToken_members[4] = {
+{
+ UA_TYPENAME("policyId") /* .memberName */
+ UA_TYPES_STRING, /* .memberTypeIndex */
+ 0, /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("userName") /* .memberName */
+ UA_TYPES_STRING, /* .memberTypeIndex */
+ offsetof(UA_UserNameIdentityToken, userName) - offsetof(UA_UserNameIdentityToken, policyId) - sizeof(UA_String), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("password") /* .memberName */
+ UA_TYPES_BYTESTRING, /* .memberTypeIndex */
+ offsetof(UA_UserNameIdentityToken, password) - offsetof(UA_UserNameIdentityToken, userName) - sizeof(UA_String), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("encryptionAlgorithm") /* .memberName */
+ UA_TYPES_STRING, /* .memberTypeIndex */
+ offsetof(UA_UserNameIdentityToken, encryptionAlgorithm) - offsetof(UA_UserNameIdentityToken, password) - sizeof(UA_ByteString), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+}};
+
+/* IdType */
+static UA_DataTypeMember IdType_members[1] = {
+{
+ UA_TYPENAME("") /* .memberName */
+ UA_TYPES_INT32, /* .memberTypeIndex */
+ 0, /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+}};
+
+/* UserTokenType */
+static UA_DataTypeMember UserTokenType_members[1] = {
+{
+ UA_TYPENAME("") /* .memberName */
+ UA_TYPES_INT32, /* .memberTypeIndex */
+ 0, /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+}};
+
+/* SetTriggeringResponse */
+static UA_DataTypeMember SetTriggeringResponse_members[5] = {
+{
+ UA_TYPENAME("responseHeader") /* .memberName */
+ UA_TYPES_RESPONSEHEADER, /* .memberTypeIndex */
+ 0, /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("addResults") /* .memberName */
+ UA_TYPES_STATUSCODE, /* .memberTypeIndex */
+ offsetof(UA_SetTriggeringResponse, addResultsSize) - offsetof(UA_SetTriggeringResponse, responseHeader) - sizeof(UA_ResponseHeader), /* .padding */
+ true, /* .namespaceZero */
+ true /* .isArray */
+},
+{
+ UA_TYPENAME("addDiagnosticInfos") /* .memberName */
+ UA_TYPES_DIAGNOSTICINFO, /* .memberTypeIndex */
+ offsetof(UA_SetTriggeringResponse, addDiagnosticInfosSize) - offsetof(UA_SetTriggeringResponse, addResults) - sizeof(void*), /* .padding */
+ true, /* .namespaceZero */
+ true /* .isArray */
+},
+{
+ UA_TYPENAME("removeResults") /* .memberName */
+ UA_TYPES_STATUSCODE, /* .memberTypeIndex */
+ offsetof(UA_SetTriggeringResponse, removeResultsSize) - offsetof(UA_SetTriggeringResponse, addDiagnosticInfos) - sizeof(void*), /* .padding */
+ true, /* .namespaceZero */
+ true /* .isArray */
+},
+{
+ UA_TYPENAME("removeDiagnosticInfos") /* .memberName */
+ UA_TYPES_DIAGNOSTICINFO, /* .memberTypeIndex */
+ offsetof(UA_SetTriggeringResponse, removeDiagnosticInfosSize) - offsetof(UA_SetTriggeringResponse, removeResults) - sizeof(void*), /* .padding */
+ true, /* .namespaceZero */
+ true /* .isArray */
+}};
+
+/* TimeZoneDataType */
+static UA_DataTypeMember TimeZoneDataType_members[2] = {
+{
+ UA_TYPENAME("offset") /* .memberName */
+ UA_TYPES_INT16, /* .memberTypeIndex */
+ 0, /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("daylightSavingInOffset") /* .memberName */
+ UA_TYPES_BOOLEAN, /* .memberTypeIndex */
+ offsetof(UA_TimeZoneDataType, daylightSavingInOffset) - offsetof(UA_TimeZoneDataType, offset) - sizeof(UA_Int16), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+}};
+
+/* ActivateSessionRequest */
+static UA_DataTypeMember ActivateSessionRequest_members[6] = {
+{
+ UA_TYPENAME("requestHeader") /* .memberName */
+ UA_TYPES_REQUESTHEADER, /* .memberTypeIndex */
+ 0, /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("clientSignature") /* .memberName */
+ UA_TYPES_SIGNATUREDATA, /* .memberTypeIndex */
+ offsetof(UA_ActivateSessionRequest, clientSignature) - offsetof(UA_ActivateSessionRequest, requestHeader) - sizeof(UA_RequestHeader), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("clientSoftwareCertificates") /* .memberName */
+ UA_TYPES_SIGNEDSOFTWARECERTIFICATE, /* .memberTypeIndex */
+ offsetof(UA_ActivateSessionRequest, clientSoftwareCertificatesSize) - offsetof(UA_ActivateSessionRequest, clientSignature) - sizeof(UA_SignatureData), /* .padding */
+ true, /* .namespaceZero */
+ true /* .isArray */
+},
+{
+ UA_TYPENAME("localeIds") /* .memberName */
+ UA_TYPES_STRING, /* .memberTypeIndex */
+ offsetof(UA_ActivateSessionRequest, localeIdsSize) - offsetof(UA_ActivateSessionRequest, clientSoftwareCertificates) - sizeof(void*), /* .padding */
+ true, /* .namespaceZero */
+ true /* .isArray */
+},
+{
+ UA_TYPENAME("userIdentityToken") /* .memberName */
+ UA_TYPES_EXTENSIONOBJECT, /* .memberTypeIndex */
+ offsetof(UA_ActivateSessionRequest, userIdentityToken) - offsetof(UA_ActivateSessionRequest, localeIds) - sizeof(void*), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("userTokenSignature") /* .memberName */
+ UA_TYPES_SIGNATUREDATA, /* .memberTypeIndex */
+ offsetof(UA_ActivateSessionRequest, userTokenSignature) - offsetof(UA_ActivateSessionRequest, userIdentityToken) - sizeof(UA_ExtensionObject), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+}};
+
+/* OpenSecureChannelResponse */
+static UA_DataTypeMember OpenSecureChannelResponse_members[4] = {
+{
+ UA_TYPENAME("responseHeader") /* .memberName */
+ UA_TYPES_RESPONSEHEADER, /* .memberTypeIndex */
+ 0, /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("serverProtocolVersion") /* .memberName */
+ UA_TYPES_UINT32, /* .memberTypeIndex */
+ offsetof(UA_OpenSecureChannelResponse, serverProtocolVersion) - offsetof(UA_OpenSecureChannelResponse, responseHeader) - sizeof(UA_ResponseHeader), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("securityToken") /* .memberName */
+ UA_TYPES_CHANNELSECURITYTOKEN, /* .memberTypeIndex */
+ offsetof(UA_OpenSecureChannelResponse, securityToken) - offsetof(UA_OpenSecureChannelResponse, serverProtocolVersion) - sizeof(UA_UInt32), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("serverNonce") /* .memberName */
+ UA_TYPES_BYTESTRING, /* .memberTypeIndex */
+ offsetof(UA_OpenSecureChannelResponse, serverNonce) - offsetof(UA_OpenSecureChannelResponse, securityToken) - sizeof(UA_ChannelSecurityToken), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+}};
+
+/* ApplicationType */
+static UA_DataTypeMember ApplicationType_members[1] = {
+{
+ UA_TYPENAME("") /* .memberName */
+ UA_TYPES_INT32, /* .memberTypeIndex */
+ 0, /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+}};
+
+/* ServerState */
+static UA_DataTypeMember ServerState_members[1] = {
+{
+ UA_TYPENAME("") /* .memberName */
+ UA_TYPES_INT32, /* .memberTypeIndex */
+ 0, /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+}};
+
+/* QueryNextResponse */
+static UA_DataTypeMember QueryNextResponse_members[3] = {
+{
+ UA_TYPENAME("responseHeader") /* .memberName */
+ UA_TYPES_RESPONSEHEADER, /* .memberTypeIndex */
+ 0, /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("queryDataSets") /* .memberName */
+ UA_TYPES_QUERYDATASET, /* .memberTypeIndex */
+ offsetof(UA_QueryNextResponse, queryDataSetsSize) - offsetof(UA_QueryNextResponse, responseHeader) - sizeof(UA_ResponseHeader), /* .padding */
+ true, /* .namespaceZero */
+ true /* .isArray */
+},
+{
+ UA_TYPENAME("revisedContinuationPoint") /* .memberName */
+ UA_TYPES_BYTESTRING, /* .memberTypeIndex */
+ offsetof(UA_QueryNextResponse, revisedContinuationPoint) - offsetof(UA_QueryNextResponse, queryDataSets) - sizeof(void*), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+}};
+
+/* DiscoveryConfiguration */
+#define DiscoveryConfiguration_members NULL
+
+/* ActivateSessionResponse */
+static UA_DataTypeMember ActivateSessionResponse_members[4] = {
+{
+ UA_TYPENAME("responseHeader") /* .memberName */
+ UA_TYPES_RESPONSEHEADER, /* .memberTypeIndex */
+ 0, /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("serverNonce") /* .memberName */
+ UA_TYPES_BYTESTRING, /* .memberTypeIndex */
+ offsetof(UA_ActivateSessionResponse, serverNonce) - offsetof(UA_ActivateSessionResponse, responseHeader) - sizeof(UA_ResponseHeader), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("results") /* .memberName */
+ UA_TYPES_STATUSCODE, /* .memberTypeIndex */
+ offsetof(UA_ActivateSessionResponse, resultsSize) - offsetof(UA_ActivateSessionResponse, serverNonce) - sizeof(UA_ByteString), /* .padding */
+ true, /* .namespaceZero */
+ true /* .isArray */
+},
+{
+ UA_TYPENAME("diagnosticInfos") /* .memberName */
+ UA_TYPES_DIAGNOSTICINFO, /* .memberTypeIndex */
+ offsetof(UA_ActivateSessionResponse, diagnosticInfosSize) - offsetof(UA_ActivateSessionResponse, results) - sizeof(void*), /* .padding */
+ true, /* .namespaceZero */
+ true /* .isArray */
+}};
+
+/* EndpointUrlListDataType */
+static UA_DataTypeMember EndpointUrlListDataType_members[1] = {
+{
+ UA_TYPENAME("endpointUrlList") /* .memberName */
+ UA_TYPES_STRING, /* .memberTypeIndex */
+ 0, /* .padding */
+ true, /* .namespaceZero */
+ true /* .isArray */
+}};
+
+/* FilterOperator */
+static UA_DataTypeMember FilterOperator_members[1] = {
+{
+ UA_TYPENAME("") /* .memberName */
+ UA_TYPES_INT32, /* .memberTypeIndex */
+ 0, /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+}};
+
+/* QueryNextRequest */
+static UA_DataTypeMember QueryNextRequest_members[3] = {
+{
+ UA_TYPENAME("requestHeader") /* .memberName */
+ UA_TYPES_REQUESTHEADER, /* .memberTypeIndex */
+ 0, /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("releaseContinuationPoint") /* .memberName */
+ UA_TYPES_BOOLEAN, /* .memberTypeIndex */
+ offsetof(UA_QueryNextRequest, releaseContinuationPoint) - offsetof(UA_QueryNextRequest, requestHeader) - sizeof(UA_RequestHeader), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("continuationPoint") /* .memberName */
+ UA_TYPES_BYTESTRING, /* .memberTypeIndex */
+ offsetof(UA_QueryNextRequest, continuationPoint) - offsetof(UA_QueryNextRequest, releaseContinuationPoint) - sizeof(UA_Boolean), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+}};
+
+/* WriteResponse */
+static UA_DataTypeMember WriteResponse_members[3] = {
+{
+ UA_TYPENAME("responseHeader") /* .memberName */
+ UA_TYPES_RESPONSEHEADER, /* .memberTypeIndex */
+ 0, /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("results") /* .memberName */
+ UA_TYPES_STATUSCODE, /* .memberTypeIndex */
+ offsetof(UA_WriteResponse, resultsSize) - offsetof(UA_WriteResponse, responseHeader) - sizeof(UA_ResponseHeader), /* .padding */
+ true, /* .namespaceZero */
+ true /* .isArray */
+},
+{
+ UA_TYPENAME("diagnosticInfos") /* .memberName */
+ UA_TYPES_DIAGNOSTICINFO, /* .memberTypeIndex */
+ offsetof(UA_WriteResponse, diagnosticInfosSize) - offsetof(UA_WriteResponse, results) - sizeof(void*), /* .padding */
+ true, /* .namespaceZero */
+ true /* .isArray */
+}};
+
+/* BrowseNextRequest */
+static UA_DataTypeMember BrowseNextRequest_members[3] = {
+{
+ UA_TYPENAME("requestHeader") /* .memberName */
+ UA_TYPES_REQUESTHEADER, /* .memberTypeIndex */
+ 0, /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("releaseContinuationPoints") /* .memberName */
+ UA_TYPES_BOOLEAN, /* .memberTypeIndex */
+ offsetof(UA_BrowseNextRequest, releaseContinuationPoints) - offsetof(UA_BrowseNextRequest, requestHeader) - sizeof(UA_RequestHeader), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("continuationPoints") /* .memberName */
+ UA_TYPES_BYTESTRING, /* .memberTypeIndex */
+ offsetof(UA_BrowseNextRequest, continuationPointsSize) - offsetof(UA_BrowseNextRequest, releaseContinuationPoints) - sizeof(UA_Boolean), /* .padding */
+ true, /* .namespaceZero */
+ true /* .isArray */
+}};
+
+/* CreateSubscriptionRequest */
+static UA_DataTypeMember CreateSubscriptionRequest_members[7] = {
+{
+ UA_TYPENAME("requestHeader") /* .memberName */
+ UA_TYPES_REQUESTHEADER, /* .memberTypeIndex */
+ 0, /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("requestedPublishingInterval") /* .memberName */
+ UA_TYPES_DOUBLE, /* .memberTypeIndex */
+ offsetof(UA_CreateSubscriptionRequest, requestedPublishingInterval) - offsetof(UA_CreateSubscriptionRequest, requestHeader) - sizeof(UA_RequestHeader), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("requestedLifetimeCount") /* .memberName */
+ UA_TYPES_UINT32, /* .memberTypeIndex */
+ offsetof(UA_CreateSubscriptionRequest, requestedLifetimeCount) - offsetof(UA_CreateSubscriptionRequest, requestedPublishingInterval) - sizeof(UA_Double), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("requestedMaxKeepAliveCount") /* .memberName */
+ UA_TYPES_UINT32, /* .memberTypeIndex */
+ offsetof(UA_CreateSubscriptionRequest, requestedMaxKeepAliveCount) - offsetof(UA_CreateSubscriptionRequest, requestedLifetimeCount) - sizeof(UA_UInt32), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("maxNotificationsPerPublish") /* .memberName */
+ UA_TYPES_UINT32, /* .memberTypeIndex */
+ offsetof(UA_CreateSubscriptionRequest, maxNotificationsPerPublish) - offsetof(UA_CreateSubscriptionRequest, requestedMaxKeepAliveCount) - sizeof(UA_UInt32), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("publishingEnabled") /* .memberName */
+ UA_TYPES_BOOLEAN, /* .memberTypeIndex */
+ offsetof(UA_CreateSubscriptionRequest, publishingEnabled) - offsetof(UA_CreateSubscriptionRequest, maxNotificationsPerPublish) - sizeof(UA_UInt32), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("priority") /* .memberName */
+ UA_TYPES_BYTE, /* .memberTypeIndex */
+ offsetof(UA_CreateSubscriptionRequest, priority) - offsetof(UA_CreateSubscriptionRequest, publishingEnabled) - sizeof(UA_Boolean), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+}};
+
+/* VariableTypeAttributes */
+static UA_DataTypeMember VariableTypeAttributes_members[10] = {
+{
+ UA_TYPENAME("specifiedAttributes") /* .memberName */
+ UA_TYPES_UINT32, /* .memberTypeIndex */
+ 0, /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("displayName") /* .memberName */
+ UA_TYPES_LOCALIZEDTEXT, /* .memberTypeIndex */
+ offsetof(UA_VariableTypeAttributes, displayName) - offsetof(UA_VariableTypeAttributes, specifiedAttributes) - sizeof(UA_UInt32), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("description") /* .memberName */
+ UA_TYPES_LOCALIZEDTEXT, /* .memberTypeIndex */
+ offsetof(UA_VariableTypeAttributes, description) - offsetof(UA_VariableTypeAttributes, displayName) - sizeof(UA_LocalizedText), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("writeMask") /* .memberName */
+ UA_TYPES_UINT32, /* .memberTypeIndex */
+ offsetof(UA_VariableTypeAttributes, writeMask) - offsetof(UA_VariableTypeAttributes, description) - sizeof(UA_LocalizedText), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("userWriteMask") /* .memberName */
+ UA_TYPES_UINT32, /* .memberTypeIndex */
+ offsetof(UA_VariableTypeAttributes, userWriteMask) - offsetof(UA_VariableTypeAttributes, writeMask) - sizeof(UA_UInt32), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("value") /* .memberName */
+ UA_TYPES_VARIANT, /* .memberTypeIndex */
+ offsetof(UA_VariableTypeAttributes, value) - offsetof(UA_VariableTypeAttributes, userWriteMask) - sizeof(UA_UInt32), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("dataType") /* .memberName */
+ UA_TYPES_NODEID, /* .memberTypeIndex */
+ offsetof(UA_VariableTypeAttributes, dataType) - offsetof(UA_VariableTypeAttributes, value) - sizeof(UA_Variant), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("valueRank") /* .memberName */
+ UA_TYPES_INT32, /* .memberTypeIndex */
+ offsetof(UA_VariableTypeAttributes, valueRank) - offsetof(UA_VariableTypeAttributes, dataType) - sizeof(UA_NodeId), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("arrayDimensions") /* .memberName */
+ UA_TYPES_UINT32, /* .memberTypeIndex */
+ offsetof(UA_VariableTypeAttributes, arrayDimensionsSize) - offsetof(UA_VariableTypeAttributes, valueRank) - sizeof(UA_Int32), /* .padding */
+ true, /* .namespaceZero */
+ true /* .isArray */
+},
+{
+ UA_TYPENAME("isAbstract") /* .memberName */
+ UA_TYPES_BOOLEAN, /* .memberTypeIndex */
+ offsetof(UA_VariableTypeAttributes, isAbstract) - offsetof(UA_VariableTypeAttributes, arrayDimensions) - sizeof(void*), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+}};
+
+/* BrowsePathResult */
+static UA_DataTypeMember BrowsePathResult_members[2] = {
+{
+ UA_TYPENAME("statusCode") /* .memberName */
+ UA_TYPES_STATUSCODE, /* .memberTypeIndex */
+ 0, /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("targets") /* .memberName */
+ UA_TYPES_BROWSEPATHTARGET, /* .memberTypeIndex */
+ offsetof(UA_BrowsePathResult, targetsSize) - offsetof(UA_BrowsePathResult, statusCode) - sizeof(UA_StatusCode), /* .padding */
+ true, /* .namespaceZero */
+ true /* .isArray */
+}};
+
+/* ModifySubscriptionResponse */
+static UA_DataTypeMember ModifySubscriptionResponse_members[4] = {
+{
+ UA_TYPENAME("responseHeader") /* .memberName */
+ UA_TYPES_RESPONSEHEADER, /* .memberTypeIndex */
+ 0, /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("revisedPublishingInterval") /* .memberName */
+ UA_TYPES_DOUBLE, /* .memberTypeIndex */
+ offsetof(UA_ModifySubscriptionResponse, revisedPublishingInterval) - offsetof(UA_ModifySubscriptionResponse, responseHeader) - sizeof(UA_ResponseHeader), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("revisedLifetimeCount") /* .memberName */
+ UA_TYPES_UINT32, /* .memberTypeIndex */
+ offsetof(UA_ModifySubscriptionResponse, revisedLifetimeCount) - offsetof(UA_ModifySubscriptionResponse, revisedPublishingInterval) - sizeof(UA_Double), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("revisedMaxKeepAliveCount") /* .memberName */
+ UA_TYPES_UINT32, /* .memberTypeIndex */
+ offsetof(UA_ModifySubscriptionResponse, revisedMaxKeepAliveCount) - offsetof(UA_ModifySubscriptionResponse, revisedLifetimeCount) - sizeof(UA_UInt32), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+}};
+
+/* RedundantServerDataType */
+static UA_DataTypeMember RedundantServerDataType_members[3] = {
+{
+ UA_TYPENAME("serverId") /* .memberName */
+ UA_TYPES_STRING, /* .memberTypeIndex */
+ 0, /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("serviceLevel") /* .memberName */
+ UA_TYPES_BYTE, /* .memberTypeIndex */
+ offsetof(UA_RedundantServerDataType, serviceLevel) - offsetof(UA_RedundantServerDataType, serverId) - sizeof(UA_String), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("serverState") /* .memberName */
+ UA_TYPES_SERVERSTATE, /* .memberTypeIndex */
+ offsetof(UA_RedundantServerDataType, serverState) - offsetof(UA_RedundantServerDataType, serviceLevel) - sizeof(UA_Byte), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+}};
+
+/* RegisterNodesResponse */
+static UA_DataTypeMember RegisterNodesResponse_members[2] = {
+{
+ UA_TYPENAME("responseHeader") /* .memberName */
+ UA_TYPES_RESPONSEHEADER, /* .memberTypeIndex */
+ 0, /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("registeredNodeIds") /* .memberName */
+ UA_TYPES_NODEID, /* .memberTypeIndex */
+ offsetof(UA_RegisterNodesResponse, registeredNodeIdsSize) - offsetof(UA_RegisterNodesResponse, responseHeader) - sizeof(UA_ResponseHeader), /* .padding */
+ true, /* .namespaceZero */
+ true /* .isArray */
+}};
+
+/* CloseSessionRequest */
+static UA_DataTypeMember CloseSessionRequest_members[2] = {
+{
+ UA_TYPENAME("requestHeader") /* .memberName */
+ UA_TYPES_REQUESTHEADER, /* .memberTypeIndex */
+ 0, /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("deleteSubscriptions") /* .memberName */
+ UA_TYPES_BOOLEAN, /* .memberTypeIndex */
+ offsetof(UA_CloseSessionRequest, deleteSubscriptions) - offsetof(UA_CloseSessionRequest, requestHeader) - sizeof(UA_RequestHeader), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+}};
+
+/* ModifyMonitoredItemsResponse */
+static UA_DataTypeMember ModifyMonitoredItemsResponse_members[3] = {
+{
+ UA_TYPENAME("responseHeader") /* .memberName */
+ UA_TYPES_RESPONSEHEADER, /* .memberTypeIndex */
+ 0, /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("results") /* .memberName */
+ UA_TYPES_MONITOREDITEMMODIFYRESULT, /* .memberTypeIndex */
+ offsetof(UA_ModifyMonitoredItemsResponse, resultsSize) - offsetof(UA_ModifyMonitoredItemsResponse, responseHeader) - sizeof(UA_ResponseHeader), /* .padding */
+ true, /* .namespaceZero */
+ true /* .isArray */
+},
+{
+ UA_TYPENAME("diagnosticInfos") /* .memberName */
+ UA_TYPES_DIAGNOSTICINFO, /* .memberTypeIndex */
+ offsetof(UA_ModifyMonitoredItemsResponse, diagnosticInfosSize) - offsetof(UA_ModifyMonitoredItemsResponse, results) - sizeof(void*), /* .padding */
+ true, /* .namespaceZero */
+ true /* .isArray */
+}};
+
+/* ModifySubscriptionRequest */
+static UA_DataTypeMember ModifySubscriptionRequest_members[7] = {
+{
+ UA_TYPENAME("requestHeader") /* .memberName */
+ UA_TYPES_REQUESTHEADER, /* .memberTypeIndex */
+ 0, /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("subscriptionId") /* .memberName */
+ UA_TYPES_UINT32, /* .memberTypeIndex */
+ offsetof(UA_ModifySubscriptionRequest, subscriptionId) - offsetof(UA_ModifySubscriptionRequest, requestHeader) - sizeof(UA_RequestHeader), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("requestedPublishingInterval") /* .memberName */
+ UA_TYPES_DOUBLE, /* .memberTypeIndex */
+ offsetof(UA_ModifySubscriptionRequest, requestedPublishingInterval) - offsetof(UA_ModifySubscriptionRequest, subscriptionId) - sizeof(UA_UInt32), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("requestedLifetimeCount") /* .memberName */
+ UA_TYPES_UINT32, /* .memberTypeIndex */
+ offsetof(UA_ModifySubscriptionRequest, requestedLifetimeCount) - offsetof(UA_ModifySubscriptionRequest, requestedPublishingInterval) - sizeof(UA_Double), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("requestedMaxKeepAliveCount") /* .memberName */
+ UA_TYPES_UINT32, /* .memberTypeIndex */
+ offsetof(UA_ModifySubscriptionRequest, requestedMaxKeepAliveCount) - offsetof(UA_ModifySubscriptionRequest, requestedLifetimeCount) - sizeof(UA_UInt32), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("maxNotificationsPerPublish") /* .memberName */
+ UA_TYPES_UINT32, /* .memberTypeIndex */
+ offsetof(UA_ModifySubscriptionRequest, maxNotificationsPerPublish) - offsetof(UA_ModifySubscriptionRequest, requestedMaxKeepAliveCount) - sizeof(UA_UInt32), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("priority") /* .memberName */
+ UA_TYPES_BYTE, /* .memberTypeIndex */
+ offsetof(UA_ModifySubscriptionRequest, priority) - offsetof(UA_ModifySubscriptionRequest, maxNotificationsPerPublish) - sizeof(UA_UInt32), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+}};
+
+/* ServerDiagnosticsSummaryDataType */
+static UA_DataTypeMember ServerDiagnosticsSummaryDataType_members[12] = {
+{
+ UA_TYPENAME("serverViewCount") /* .memberName */
+ UA_TYPES_UINT32, /* .memberTypeIndex */
+ 0, /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("currentSessionCount") /* .memberName */
+ UA_TYPES_UINT32, /* .memberTypeIndex */
+ offsetof(UA_ServerDiagnosticsSummaryDataType, currentSessionCount) - offsetof(UA_ServerDiagnosticsSummaryDataType, serverViewCount) - sizeof(UA_UInt32), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("cumulatedSessionCount") /* .memberName */
+ UA_TYPES_UINT32, /* .memberTypeIndex */
+ offsetof(UA_ServerDiagnosticsSummaryDataType, cumulatedSessionCount) - offsetof(UA_ServerDiagnosticsSummaryDataType, currentSessionCount) - sizeof(UA_UInt32), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("securityRejectedSessionCount") /* .memberName */
+ UA_TYPES_UINT32, /* .memberTypeIndex */
+ offsetof(UA_ServerDiagnosticsSummaryDataType, securityRejectedSessionCount) - offsetof(UA_ServerDiagnosticsSummaryDataType, cumulatedSessionCount) - sizeof(UA_UInt32), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("rejectedSessionCount") /* .memberName */
+ UA_TYPES_UINT32, /* .memberTypeIndex */
+ offsetof(UA_ServerDiagnosticsSummaryDataType, rejectedSessionCount) - offsetof(UA_ServerDiagnosticsSummaryDataType, securityRejectedSessionCount) - sizeof(UA_UInt32), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("sessionTimeoutCount") /* .memberName */
+ UA_TYPES_UINT32, /* .memberTypeIndex */
+ offsetof(UA_ServerDiagnosticsSummaryDataType, sessionTimeoutCount) - offsetof(UA_ServerDiagnosticsSummaryDataType, rejectedSessionCount) - sizeof(UA_UInt32), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("sessionAbortCount") /* .memberName */
+ UA_TYPES_UINT32, /* .memberTypeIndex */
+ offsetof(UA_ServerDiagnosticsSummaryDataType, sessionAbortCount) - offsetof(UA_ServerDiagnosticsSummaryDataType, sessionTimeoutCount) - sizeof(UA_UInt32), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("currentSubscriptionCount") /* .memberName */
+ UA_TYPES_UINT32, /* .memberTypeIndex */
+ offsetof(UA_ServerDiagnosticsSummaryDataType, currentSubscriptionCount) - offsetof(UA_ServerDiagnosticsSummaryDataType, sessionAbortCount) - sizeof(UA_UInt32), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("cumulatedSubscriptionCount") /* .memberName */
+ UA_TYPES_UINT32, /* .memberTypeIndex */
+ offsetof(UA_ServerDiagnosticsSummaryDataType, cumulatedSubscriptionCount) - offsetof(UA_ServerDiagnosticsSummaryDataType, currentSubscriptionCount) - sizeof(UA_UInt32), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("publishingIntervalCount") /* .memberName */
+ UA_TYPES_UINT32, /* .memberTypeIndex */
+ offsetof(UA_ServerDiagnosticsSummaryDataType, publishingIntervalCount) - offsetof(UA_ServerDiagnosticsSummaryDataType, cumulatedSubscriptionCount) - sizeof(UA_UInt32), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("securityRejectedRequestsCount") /* .memberName */
+ UA_TYPES_UINT32, /* .memberTypeIndex */
+ offsetof(UA_ServerDiagnosticsSummaryDataType, securityRejectedRequestsCount) - offsetof(UA_ServerDiagnosticsSummaryDataType, publishingIntervalCount) - sizeof(UA_UInt32), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("rejectedRequestsCount") /* .memberName */
+ UA_TYPES_UINT32, /* .memberTypeIndex */
+ offsetof(UA_ServerDiagnosticsSummaryDataType, rejectedRequestsCount) - offsetof(UA_ServerDiagnosticsSummaryDataType, securityRejectedRequestsCount) - sizeof(UA_UInt32), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+}};
+
+/* UserTokenPolicy */
+static UA_DataTypeMember UserTokenPolicy_members[5] = {
+{
+ UA_TYPENAME("policyId") /* .memberName */
+ UA_TYPES_STRING, /* .memberTypeIndex */
+ 0, /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("tokenType") /* .memberName */
+ UA_TYPES_USERTOKENTYPE, /* .memberTypeIndex */
+ offsetof(UA_UserTokenPolicy, tokenType) - offsetof(UA_UserTokenPolicy, policyId) - sizeof(UA_String), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("issuedTokenType") /* .memberName */
+ UA_TYPES_STRING, /* .memberTypeIndex */
+ offsetof(UA_UserTokenPolicy, issuedTokenType) - offsetof(UA_UserTokenPolicy, tokenType) - sizeof(UA_UserTokenType), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("issuerEndpointUrl") /* .memberName */
+ UA_TYPES_STRING, /* .memberTypeIndex */
+ offsetof(UA_UserTokenPolicy, issuerEndpointUrl) - offsetof(UA_UserTokenPolicy, issuedTokenType) - sizeof(UA_String), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("securityPolicyUri") /* .memberName */
+ UA_TYPES_STRING, /* .memberTypeIndex */
+ offsetof(UA_UserTokenPolicy, securityPolicyUri) - offsetof(UA_UserTokenPolicy, issuerEndpointUrl) - sizeof(UA_String), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+}};
+
+/* ReferenceTypeAttributes */
+static UA_DataTypeMember ReferenceTypeAttributes_members[8] = {
+{
+ UA_TYPENAME("specifiedAttributes") /* .memberName */
+ UA_TYPES_UINT32, /* .memberTypeIndex */
+ 0, /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("displayName") /* .memberName */
+ UA_TYPES_LOCALIZEDTEXT, /* .memberTypeIndex */
+ offsetof(UA_ReferenceTypeAttributes, displayName) - offsetof(UA_ReferenceTypeAttributes, specifiedAttributes) - sizeof(UA_UInt32), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("description") /* .memberName */
+ UA_TYPES_LOCALIZEDTEXT, /* .memberTypeIndex */
+ offsetof(UA_ReferenceTypeAttributes, description) - offsetof(UA_ReferenceTypeAttributes, displayName) - sizeof(UA_LocalizedText), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("writeMask") /* .memberName */
+ UA_TYPES_UINT32, /* .memberTypeIndex */
+ offsetof(UA_ReferenceTypeAttributes, writeMask) - offsetof(UA_ReferenceTypeAttributes, description) - sizeof(UA_LocalizedText), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("userWriteMask") /* .memberName */
+ UA_TYPES_UINT32, /* .memberTypeIndex */
+ offsetof(UA_ReferenceTypeAttributes, userWriteMask) - offsetof(UA_ReferenceTypeAttributes, writeMask) - sizeof(UA_UInt32), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("isAbstract") /* .memberName */
+ UA_TYPES_BOOLEAN, /* .memberTypeIndex */
+ offsetof(UA_ReferenceTypeAttributes, isAbstract) - offsetof(UA_ReferenceTypeAttributes, userWriteMask) - sizeof(UA_UInt32), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("symmetric") /* .memberName */
+ UA_TYPES_BOOLEAN, /* .memberTypeIndex */
+ offsetof(UA_ReferenceTypeAttributes, symmetric) - offsetof(UA_ReferenceTypeAttributes, isAbstract) - sizeof(UA_Boolean), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("inverseName") /* .memberName */
+ UA_TYPES_LOCALIZEDTEXT, /* .memberTypeIndex */
+ offsetof(UA_ReferenceTypeAttributes, inverseName) - offsetof(UA_ReferenceTypeAttributes, symmetric) - sizeof(UA_Boolean), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+}};
+
+/* BrowsePath */
+static UA_DataTypeMember BrowsePath_members[2] = {
+{
+ UA_TYPENAME("startingNode") /* .memberName */
+ UA_TYPES_NODEID, /* .memberTypeIndex */
+ 0, /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("relativePath") /* .memberName */
+ UA_TYPES_RELATIVEPATH, /* .memberTypeIndex */
+ offsetof(UA_BrowsePath, relativePath) - offsetof(UA_BrowsePath, startingNode) - sizeof(UA_NodeId), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+}};
+
+/* SetMonitoringModeRequest */
+static UA_DataTypeMember SetMonitoringModeRequest_members[4] = {
+{
+ UA_TYPENAME("requestHeader") /* .memberName */
+ UA_TYPES_REQUESTHEADER, /* .memberTypeIndex */
+ 0, /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("subscriptionId") /* .memberName */
+ UA_TYPES_UINT32, /* .memberTypeIndex */
+ offsetof(UA_SetMonitoringModeRequest, subscriptionId) - offsetof(UA_SetMonitoringModeRequest, requestHeader) - sizeof(UA_RequestHeader), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("monitoringMode") /* .memberName */
+ UA_TYPES_MONITORINGMODE, /* .memberTypeIndex */
+ offsetof(UA_SetMonitoringModeRequest, monitoringMode) - offsetof(UA_SetMonitoringModeRequest, subscriptionId) - sizeof(UA_UInt32), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("monitoredItemIds") /* .memberName */
+ UA_TYPES_UINT32, /* .memberTypeIndex */
+ offsetof(UA_SetMonitoringModeRequest, monitoredItemIdsSize) - offsetof(UA_SetMonitoringModeRequest, monitoringMode) - sizeof(UA_MonitoringMode), /* .padding */
+ true, /* .namespaceZero */
+ true /* .isArray */
+}};
+
+/* UnregisterNodesResponse */
+static UA_DataTypeMember UnregisterNodesResponse_members[1] = {
+{
+ UA_TYPENAME("responseHeader") /* .memberName */
+ UA_TYPES_RESPONSEHEADER, /* .memberTypeIndex */
+ 0, /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+}};
+
+/* WriteRequest */
+static UA_DataTypeMember WriteRequest_members[2] = {
+{
+ UA_TYPENAME("requestHeader") /* .memberName */
+ UA_TYPES_REQUESTHEADER, /* .memberTypeIndex */
+ 0, /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("nodesToWrite") /* .memberName */
+ UA_TYPES_WRITEVALUE, /* .memberTypeIndex */
+ offsetof(UA_WriteRequest, nodesToWriteSize) - offsetof(UA_WriteRequest, requestHeader) - sizeof(UA_RequestHeader), /* .padding */
+ true, /* .namespaceZero */
+ true /* .isArray */
+}};
+
+/* ObjectAttributes */
+static UA_DataTypeMember ObjectAttributes_members[6] = {
+{
+ UA_TYPENAME("specifiedAttributes") /* .memberName */
+ UA_TYPES_UINT32, /* .memberTypeIndex */
+ 0, /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("displayName") /* .memberName */
+ UA_TYPES_LOCALIZEDTEXT, /* .memberTypeIndex */
+ offsetof(UA_ObjectAttributes, displayName) - offsetof(UA_ObjectAttributes, specifiedAttributes) - sizeof(UA_UInt32), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("description") /* .memberName */
+ UA_TYPES_LOCALIZEDTEXT, /* .memberTypeIndex */
+ offsetof(UA_ObjectAttributes, description) - offsetof(UA_ObjectAttributes, displayName) - sizeof(UA_LocalizedText), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("writeMask") /* .memberName */
+ UA_TYPES_UINT32, /* .memberTypeIndex */
+ offsetof(UA_ObjectAttributes, writeMask) - offsetof(UA_ObjectAttributes, description) - sizeof(UA_LocalizedText), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("userWriteMask") /* .memberName */
+ UA_TYPES_UINT32, /* .memberTypeIndex */
+ offsetof(UA_ObjectAttributes, userWriteMask) - offsetof(UA_ObjectAttributes, writeMask) - sizeof(UA_UInt32), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("eventNotifier") /* .memberName */
+ UA_TYPES_BYTE, /* .memberTypeIndex */
+ offsetof(UA_ObjectAttributes, eventNotifier) - offsetof(UA_ObjectAttributes, userWriteMask) - sizeof(UA_UInt32), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+}};
+
+/* BrowseResultMask */
+static UA_DataTypeMember BrowseResultMask_members[1] = {
+{
+ UA_TYPENAME("") /* .memberName */
+ UA_TYPES_INT32, /* .memberTypeIndex */
+ 0, /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+}};
+
+/* BrowseDescription */
+static UA_DataTypeMember BrowseDescription_members[6] = {
+{
+ UA_TYPENAME("nodeId") /* .memberName */
+ UA_TYPES_NODEID, /* .memberTypeIndex */
+ 0, /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("browseDirection") /* .memberName */
+ UA_TYPES_BROWSEDIRECTION, /* .memberTypeIndex */
+ offsetof(UA_BrowseDescription, browseDirection) - offsetof(UA_BrowseDescription, nodeId) - sizeof(UA_NodeId), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("referenceTypeId") /* .memberName */
+ UA_TYPES_NODEID, /* .memberTypeIndex */
+ offsetof(UA_BrowseDescription, referenceTypeId) - offsetof(UA_BrowseDescription, browseDirection) - sizeof(UA_BrowseDirection), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("includeSubtypes") /* .memberName */
+ UA_TYPES_BOOLEAN, /* .memberTypeIndex */
+ offsetof(UA_BrowseDescription, includeSubtypes) - offsetof(UA_BrowseDescription, referenceTypeId) - sizeof(UA_NodeId), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("nodeClassMask") /* .memberName */
+ UA_TYPES_UINT32, /* .memberTypeIndex */
+ offsetof(UA_BrowseDescription, nodeClassMask) - offsetof(UA_BrowseDescription, includeSubtypes) - sizeof(UA_Boolean), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("resultMask") /* .memberName */
+ UA_TYPES_UINT32, /* .memberTypeIndex */
+ offsetof(UA_BrowseDescription, resultMask) - offsetof(UA_BrowseDescription, nodeClassMask) - sizeof(UA_UInt32), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+}};
+
+/* SetTriggeringRequest */
+static UA_DataTypeMember SetTriggeringRequest_members[5] = {
+{
+ UA_TYPENAME("requestHeader") /* .memberName */
+ UA_TYPES_REQUESTHEADER, /* .memberTypeIndex */
+ 0, /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("subscriptionId") /* .memberName */
+ UA_TYPES_UINT32, /* .memberTypeIndex */
+ offsetof(UA_SetTriggeringRequest, subscriptionId) - offsetof(UA_SetTriggeringRequest, requestHeader) - sizeof(UA_RequestHeader), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("triggeringItemId") /* .memberName */
+ UA_TYPES_UINT32, /* .memberTypeIndex */
+ offsetof(UA_SetTriggeringRequest, triggeringItemId) - offsetof(UA_SetTriggeringRequest, subscriptionId) - sizeof(UA_UInt32), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("linksToAdd") /* .memberName */
+ UA_TYPES_UINT32, /* .memberTypeIndex */
+ offsetof(UA_SetTriggeringRequest, linksToAddSize) - offsetof(UA_SetTriggeringRequest, triggeringItemId) - sizeof(UA_UInt32), /* .padding */
+ true, /* .namespaceZero */
+ true /* .isArray */
+},
+{
+ UA_TYPENAME("linksToRemove") /* .memberName */
+ UA_TYPES_UINT32, /* .memberTypeIndex */
+ offsetof(UA_SetTriggeringRequest, linksToRemoveSize) - offsetof(UA_SetTriggeringRequest, linksToAdd) - sizeof(void*), /* .padding */
+ true, /* .namespaceZero */
+ true /* .isArray */
+}};
+
+/* SessionSecurityDiagnosticsDataType */
+static UA_DataTypeMember SessionSecurityDiagnosticsDataType_members[9] = {
+{
+ UA_TYPENAME("sessionId") /* .memberName */
+ UA_TYPES_NODEID, /* .memberTypeIndex */
+ 0, /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("clientUserIdOfSession") /* .memberName */
+ UA_TYPES_STRING, /* .memberTypeIndex */
+ offsetof(UA_SessionSecurityDiagnosticsDataType, clientUserIdOfSession) - offsetof(UA_SessionSecurityDiagnosticsDataType, sessionId) - sizeof(UA_NodeId), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("clientUserIdHistory") /* .memberName */
+ UA_TYPES_STRING, /* .memberTypeIndex */
+ offsetof(UA_SessionSecurityDiagnosticsDataType, clientUserIdHistorySize) - offsetof(UA_SessionSecurityDiagnosticsDataType, clientUserIdOfSession) - sizeof(UA_String), /* .padding */
+ true, /* .namespaceZero */
+ true /* .isArray */
+},
+{
+ UA_TYPENAME("authenticationMechanism") /* .memberName */
+ UA_TYPES_STRING, /* .memberTypeIndex */
+ offsetof(UA_SessionSecurityDiagnosticsDataType, authenticationMechanism) - offsetof(UA_SessionSecurityDiagnosticsDataType, clientUserIdHistory) - sizeof(void*), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("encoding") /* .memberName */
+ UA_TYPES_STRING, /* .memberTypeIndex */
+ offsetof(UA_SessionSecurityDiagnosticsDataType, encoding) - offsetof(UA_SessionSecurityDiagnosticsDataType, authenticationMechanism) - sizeof(UA_String), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("transportProtocol") /* .memberName */
+ UA_TYPES_STRING, /* .memberTypeIndex */
+ offsetof(UA_SessionSecurityDiagnosticsDataType, transportProtocol) - offsetof(UA_SessionSecurityDiagnosticsDataType, encoding) - sizeof(UA_String), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("securityMode") /* .memberName */
+ UA_TYPES_MESSAGESECURITYMODE, /* .memberTypeIndex */
+ offsetof(UA_SessionSecurityDiagnosticsDataType, securityMode) - offsetof(UA_SessionSecurityDiagnosticsDataType, transportProtocol) - sizeof(UA_String), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("securityPolicyUri") /* .memberName */
+ UA_TYPES_STRING, /* .memberTypeIndex */
+ offsetof(UA_SessionSecurityDiagnosticsDataType, securityPolicyUri) - offsetof(UA_SessionSecurityDiagnosticsDataType, securityMode) - sizeof(UA_MessageSecurityMode), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("clientCertificate") /* .memberName */
+ UA_TYPES_BYTESTRING, /* .memberTypeIndex */
+ offsetof(UA_SessionSecurityDiagnosticsDataType, clientCertificate) - offsetof(UA_SessionSecurityDiagnosticsDataType, securityPolicyUri) - sizeof(UA_String), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+}};
+
+/* RepublishRequest */
+static UA_DataTypeMember RepublishRequest_members[3] = {
+{
+ UA_TYPENAME("requestHeader") /* .memberName */
+ UA_TYPES_REQUESTHEADER, /* .memberTypeIndex */
+ 0, /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("subscriptionId") /* .memberName */
+ UA_TYPES_UINT32, /* .memberTypeIndex */
+ offsetof(UA_RepublishRequest, subscriptionId) - offsetof(UA_RepublishRequest, requestHeader) - sizeof(UA_RequestHeader), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("retransmitSequenceNumber") /* .memberName */
+ UA_TYPES_UINT32, /* .memberTypeIndex */
+ offsetof(UA_RepublishRequest, retransmitSequenceNumber) - offsetof(UA_RepublishRequest, subscriptionId) - sizeof(UA_UInt32), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+}};
+
+/* GetEndpointsRequest */
+static UA_DataTypeMember GetEndpointsRequest_members[4] = {
+{
+ UA_TYPENAME("requestHeader") /* .memberName */
+ UA_TYPES_REQUESTHEADER, /* .memberTypeIndex */
+ 0, /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("endpointUrl") /* .memberName */
+ UA_TYPES_STRING, /* .memberTypeIndex */
+ offsetof(UA_GetEndpointsRequest, endpointUrl) - offsetof(UA_GetEndpointsRequest, requestHeader) - sizeof(UA_RequestHeader), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("localeIds") /* .memberName */
+ UA_TYPES_STRING, /* .memberTypeIndex */
+ offsetof(UA_GetEndpointsRequest, localeIdsSize) - offsetof(UA_GetEndpointsRequest, endpointUrl) - sizeof(UA_String), /* .padding */
+ true, /* .namespaceZero */
+ true /* .isArray */
+},
+{
+ UA_TYPENAME("profileUris") /* .memberName */
+ UA_TYPES_STRING, /* .memberTypeIndex */
+ offsetof(UA_GetEndpointsRequest, profileUrisSize) - offsetof(UA_GetEndpointsRequest, localeIds) - sizeof(void*), /* .padding */
+ true, /* .namespaceZero */
+ true /* .isArray */
+}};
+
+/* PublishRequest */
+static UA_DataTypeMember PublishRequest_members[2] = {
+{
+ UA_TYPENAME("requestHeader") /* .memberName */
+ UA_TYPES_REQUESTHEADER, /* .memberTypeIndex */
+ 0, /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("subscriptionAcknowledgements") /* .memberName */
+ UA_TYPES_SUBSCRIPTIONACKNOWLEDGEMENT, /* .memberTypeIndex */
+ offsetof(UA_PublishRequest, subscriptionAcknowledgementsSize) - offsetof(UA_PublishRequest, requestHeader) - sizeof(UA_RequestHeader), /* .padding */
+ true, /* .namespaceZero */
+ true /* .isArray */
+}};
+
+/* DeleteSubscriptionsResponse */
+static UA_DataTypeMember DeleteSubscriptionsResponse_members[3] = {
+{
+ UA_TYPENAME("responseHeader") /* .memberName */
+ UA_TYPES_RESPONSEHEADER, /* .memberTypeIndex */
+ 0, /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("results") /* .memberName */
+ UA_TYPES_STATUSCODE, /* .memberTypeIndex */
+ offsetof(UA_DeleteSubscriptionsResponse, resultsSize) - offsetof(UA_DeleteSubscriptionsResponse, responseHeader) - sizeof(UA_ResponseHeader), /* .padding */
+ true, /* .namespaceZero */
+ true /* .isArray */
+},
+{
+ UA_TYPENAME("diagnosticInfos") /* .memberName */
+ UA_TYPES_DIAGNOSTICINFO, /* .memberTypeIndex */
+ offsetof(UA_DeleteSubscriptionsResponse, diagnosticInfosSize) - offsetof(UA_DeleteSubscriptionsResponse, results) - sizeof(void*), /* .padding */
+ true, /* .namespaceZero */
+ true /* .isArray */
+}};
+
+/* AddNodesResponse */
+static UA_DataTypeMember AddNodesResponse_members[3] = {
+{
+ UA_TYPENAME("responseHeader") /* .memberName */
+ UA_TYPES_RESPONSEHEADER, /* .memberTypeIndex */
+ 0, /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("results") /* .memberName */
+ UA_TYPES_ADDNODESRESULT, /* .memberTypeIndex */
+ offsetof(UA_AddNodesResponse, resultsSize) - offsetof(UA_AddNodesResponse, responseHeader) - sizeof(UA_ResponseHeader), /* .padding */
+ true, /* .namespaceZero */
+ true /* .isArray */
+},
+{
+ UA_TYPENAME("diagnosticInfos") /* .memberName */
+ UA_TYPES_DIAGNOSTICINFO, /* .memberTypeIndex */
+ offsetof(UA_AddNodesResponse, diagnosticInfosSize) - offsetof(UA_AddNodesResponse, results) - sizeof(void*), /* .padding */
+ true, /* .namespaceZero */
+ true /* .isArray */
+}};
+
+/* DataChangeNotification */
+static UA_DataTypeMember DataChangeNotification_members[2] = {
+{
+ UA_TYPENAME("monitoredItems") /* .memberName */
+ UA_TYPES_MONITOREDITEMNOTIFICATION, /* .memberTypeIndex */
+ 0, /* .padding */
+ true, /* .namespaceZero */
+ true /* .isArray */
+},
+{
+ UA_TYPENAME("diagnosticInfos") /* .memberName */
+ UA_TYPES_DIAGNOSTICINFO, /* .memberTypeIndex */
+ offsetof(UA_DataChangeNotification, diagnosticInfosSize) - offsetof(UA_DataChangeNotification, monitoredItems) - sizeof(void*), /* .padding */
+ true, /* .namespaceZero */
+ true /* .isArray */
+}};
+
+/* CloseSecureChannelResponse */
+static UA_DataTypeMember CloseSecureChannelResponse_members[1] = {
+{
+ UA_TYPENAME("responseHeader") /* .memberName */
+ UA_TYPES_RESPONSEHEADER, /* .memberTypeIndex */
+ 0, /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+}};
+
+/* ModifyMonitoredItemsRequest */
+static UA_DataTypeMember ModifyMonitoredItemsRequest_members[4] = {
+{
+ UA_TYPENAME("requestHeader") /* .memberName */
+ UA_TYPES_REQUESTHEADER, /* .memberTypeIndex */
+ 0, /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("subscriptionId") /* .memberName */
+ UA_TYPES_UINT32, /* .memberTypeIndex */
+ offsetof(UA_ModifyMonitoredItemsRequest, subscriptionId) - offsetof(UA_ModifyMonitoredItemsRequest, requestHeader) - sizeof(UA_RequestHeader), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("timestampsToReturn") /* .memberName */
+ UA_TYPES_TIMESTAMPSTORETURN, /* .memberTypeIndex */
+ offsetof(UA_ModifyMonitoredItemsRequest, timestampsToReturn) - offsetof(UA_ModifyMonitoredItemsRequest, subscriptionId) - sizeof(UA_UInt32), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("itemsToModify") /* .memberName */
+ UA_TYPES_MONITOREDITEMMODIFYREQUEST, /* .memberTypeIndex */
+ offsetof(UA_ModifyMonitoredItemsRequest, itemsToModifySize) - offsetof(UA_ModifyMonitoredItemsRequest, timestampsToReturn) - sizeof(UA_TimestampsToReturn), /* .padding */
+ true, /* .namespaceZero */
+ true /* .isArray */
+}};
+
+/* SetMonitoringModeResponse */
+static UA_DataTypeMember SetMonitoringModeResponse_members[3] = {
+{
+ UA_TYPENAME("responseHeader") /* .memberName */
+ UA_TYPES_RESPONSEHEADER, /* .memberTypeIndex */
+ 0, /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("results") /* .memberName */
+ UA_TYPES_STATUSCODE, /* .memberTypeIndex */
+ offsetof(UA_SetMonitoringModeResponse, resultsSize) - offsetof(UA_SetMonitoringModeResponse, responseHeader) - sizeof(UA_ResponseHeader), /* .padding */
+ true, /* .namespaceZero */
+ true /* .isArray */
+},
+{
+ UA_TYPENAME("diagnosticInfos") /* .memberName */
+ UA_TYPES_DIAGNOSTICINFO, /* .memberTypeIndex */
+ offsetof(UA_SetMonitoringModeResponse, diagnosticInfosSize) - offsetof(UA_SetMonitoringModeResponse, results) - sizeof(void*), /* .padding */
+ true, /* .namespaceZero */
+ true /* .isArray */
+}};
+
+/* FindServersRequest */
+static UA_DataTypeMember FindServersRequest_members[4] = {
+{
+ UA_TYPENAME("requestHeader") /* .memberName */
+ UA_TYPES_REQUESTHEADER, /* .memberTypeIndex */
+ 0, /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("endpointUrl") /* .memberName */
+ UA_TYPES_STRING, /* .memberTypeIndex */
+ offsetof(UA_FindServersRequest, endpointUrl) - offsetof(UA_FindServersRequest, requestHeader) - sizeof(UA_RequestHeader), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("localeIds") /* .memberName */
+ UA_TYPES_STRING, /* .memberTypeIndex */
+ offsetof(UA_FindServersRequest, localeIdsSize) - offsetof(UA_FindServersRequest, endpointUrl) - sizeof(UA_String), /* .padding */
+ true, /* .namespaceZero */
+ true /* .isArray */
+},
+{
+ UA_TYPENAME("serverUris") /* .memberName */
+ UA_TYPES_STRING, /* .memberTypeIndex */
+ offsetof(UA_FindServersRequest, serverUrisSize) - offsetof(UA_FindServersRequest, localeIds) - sizeof(void*), /* .padding */
+ true, /* .namespaceZero */
+ true /* .isArray */
+}};
+
+/* ReferenceDescription */
+static UA_DataTypeMember ReferenceDescription_members[7] = {
+{
+ UA_TYPENAME("referenceTypeId") /* .memberName */
+ UA_TYPES_NODEID, /* .memberTypeIndex */
+ 0, /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("isForward") /* .memberName */
+ UA_TYPES_BOOLEAN, /* .memberTypeIndex */
+ offsetof(UA_ReferenceDescription, isForward) - offsetof(UA_ReferenceDescription, referenceTypeId) - sizeof(UA_NodeId), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("nodeId") /* .memberName */
+ UA_TYPES_EXPANDEDNODEID, /* .memberTypeIndex */
+ offsetof(UA_ReferenceDescription, nodeId) - offsetof(UA_ReferenceDescription, isForward) - sizeof(UA_Boolean), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("browseName") /* .memberName */
+ UA_TYPES_QUALIFIEDNAME, /* .memberTypeIndex */
+ offsetof(UA_ReferenceDescription, browseName) - offsetof(UA_ReferenceDescription, nodeId) - sizeof(UA_ExpandedNodeId), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("displayName") /* .memberName */
+ UA_TYPES_LOCALIZEDTEXT, /* .memberTypeIndex */
+ offsetof(UA_ReferenceDescription, displayName) - offsetof(UA_ReferenceDescription, browseName) - sizeof(UA_QualifiedName), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("nodeClass") /* .memberName */
+ UA_TYPES_NODECLASS, /* .memberTypeIndex */
+ offsetof(UA_ReferenceDescription, nodeClass) - offsetof(UA_ReferenceDescription, displayName) - sizeof(UA_LocalizedText), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("typeDefinition") /* .memberName */
+ UA_TYPES_EXPANDEDNODEID, /* .memberTypeIndex */
+ offsetof(UA_ReferenceDescription, typeDefinition) - offsetof(UA_ReferenceDescription, nodeClass) - sizeof(UA_NodeClass), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+}};
+
+/* SetPublishingModeResponse */
+static UA_DataTypeMember SetPublishingModeResponse_members[3] = {
+{
+ UA_TYPENAME("responseHeader") /* .memberName */
+ UA_TYPES_RESPONSEHEADER, /* .memberTypeIndex */
+ 0, /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("results") /* .memberName */
+ UA_TYPES_STATUSCODE, /* .memberTypeIndex */
+ offsetof(UA_SetPublishingModeResponse, resultsSize) - offsetof(UA_SetPublishingModeResponse, responseHeader) - sizeof(UA_ResponseHeader), /* .padding */
+ true, /* .namespaceZero */
+ true /* .isArray */
+},
+{
+ UA_TYPENAME("diagnosticInfos") /* .memberName */
+ UA_TYPES_DIAGNOSTICINFO, /* .memberTypeIndex */
+ offsetof(UA_SetPublishingModeResponse, diagnosticInfosSize) - offsetof(UA_SetPublishingModeResponse, results) - sizeof(void*), /* .padding */
+ true, /* .namespaceZero */
+ true /* .isArray */
+}};
+
+/* ContentFilterResult */
+static UA_DataTypeMember ContentFilterResult_members[2] = {
+{
+ UA_TYPENAME("elementResults") /* .memberName */
+ UA_TYPES_CONTENTFILTERELEMENTRESULT, /* .memberTypeIndex */
+ 0, /* .padding */
+ true, /* .namespaceZero */
+ true /* .isArray */
+},
+{
+ UA_TYPENAME("elementDiagnosticInfos") /* .memberName */
+ UA_TYPES_DIAGNOSTICINFO, /* .memberTypeIndex */
+ offsetof(UA_ContentFilterResult, elementDiagnosticInfosSize) - offsetof(UA_ContentFilterResult, elementResults) - sizeof(void*), /* .padding */
+ true, /* .namespaceZero */
+ true /* .isArray */
+}};
+
+/* RegisterServerResponse */
+static UA_DataTypeMember RegisterServerResponse_members[1] = {
+{
+ UA_TYPENAME("responseHeader") /* .memberName */
+ UA_TYPES_RESPONSEHEADER, /* .memberTypeIndex */
+ 0, /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+}};
+
+/* AddReferencesItem */
+static UA_DataTypeMember AddReferencesItem_members[6] = {
+{
+ UA_TYPENAME("sourceNodeId") /* .memberName */
+ UA_TYPES_NODEID, /* .memberTypeIndex */
+ 0, /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("referenceTypeId") /* .memberName */
+ UA_TYPES_NODEID, /* .memberTypeIndex */
+ offsetof(UA_AddReferencesItem, referenceTypeId) - offsetof(UA_AddReferencesItem, sourceNodeId) - sizeof(UA_NodeId), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("isForward") /* .memberName */
+ UA_TYPES_BOOLEAN, /* .memberTypeIndex */
+ offsetof(UA_AddReferencesItem, isForward) - offsetof(UA_AddReferencesItem, referenceTypeId) - sizeof(UA_NodeId), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("targetServerUri") /* .memberName */
+ UA_TYPES_STRING, /* .memberTypeIndex */
+ offsetof(UA_AddReferencesItem, targetServerUri) - offsetof(UA_AddReferencesItem, isForward) - sizeof(UA_Boolean), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("targetNodeId") /* .memberName */
+ UA_TYPES_EXPANDEDNODEID, /* .memberTypeIndex */
+ offsetof(UA_AddReferencesItem, targetNodeId) - offsetof(UA_AddReferencesItem, targetServerUri) - sizeof(UA_String), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("targetNodeClass") /* .memberName */
+ UA_TYPES_NODECLASS, /* .memberTypeIndex */
+ offsetof(UA_AddReferencesItem, targetNodeClass) - offsetof(UA_AddReferencesItem, targetNodeId) - sizeof(UA_ExpandedNodeId), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+}};
+
+/* QueryDataDescription */
+static UA_DataTypeMember QueryDataDescription_members[3] = {
+{
+ UA_TYPENAME("relativePath") /* .memberName */
+ UA_TYPES_RELATIVEPATH, /* .memberTypeIndex */
+ 0, /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("attributeId") /* .memberName */
+ UA_TYPES_UINT32, /* .memberTypeIndex */
+ offsetof(UA_QueryDataDescription, attributeId) - offsetof(UA_QueryDataDescription, relativePath) - sizeof(UA_RelativePath), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("indexRange") /* .memberName */
+ UA_TYPES_STRING, /* .memberTypeIndex */
+ offsetof(UA_QueryDataDescription, indexRange) - offsetof(UA_QueryDataDescription, attributeId) - sizeof(UA_UInt32), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+}};
+
+/* CreateSubscriptionResponse */
+static UA_DataTypeMember CreateSubscriptionResponse_members[5] = {
+{
+ UA_TYPENAME("responseHeader") /* .memberName */
+ UA_TYPES_RESPONSEHEADER, /* .memberTypeIndex */
+ 0, /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("subscriptionId") /* .memberName */
+ UA_TYPES_UINT32, /* .memberTypeIndex */
+ offsetof(UA_CreateSubscriptionResponse, subscriptionId) - offsetof(UA_CreateSubscriptionResponse, responseHeader) - sizeof(UA_ResponseHeader), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("revisedPublishingInterval") /* .memberName */
+ UA_TYPES_DOUBLE, /* .memberTypeIndex */
+ offsetof(UA_CreateSubscriptionResponse, revisedPublishingInterval) - offsetof(UA_CreateSubscriptionResponse, subscriptionId) - sizeof(UA_UInt32), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("revisedLifetimeCount") /* .memberName */
+ UA_TYPES_UINT32, /* .memberTypeIndex */
+ offsetof(UA_CreateSubscriptionResponse, revisedLifetimeCount) - offsetof(UA_CreateSubscriptionResponse, revisedPublishingInterval) - sizeof(UA_Double), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("revisedMaxKeepAliveCount") /* .memberName */
+ UA_TYPES_UINT32, /* .memberTypeIndex */
+ offsetof(UA_CreateSubscriptionResponse, revisedMaxKeepAliveCount) - offsetof(UA_CreateSubscriptionResponse, revisedLifetimeCount) - sizeof(UA_UInt32), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+}};
+
+/* NetworkGroupDataType */
+static UA_DataTypeMember NetworkGroupDataType_members[2] = {
+{
+ UA_TYPENAME("serverUri") /* .memberName */
+ UA_TYPES_STRING, /* .memberTypeIndex */
+ 0, /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("networkPaths") /* .memberName */
+ UA_TYPES_ENDPOINTURLLISTDATATYPE, /* .memberTypeIndex */
+ offsetof(UA_NetworkGroupDataType, networkPathsSize) - offsetof(UA_NetworkGroupDataType, serverUri) - sizeof(UA_String), /* .padding */
+ true, /* .namespaceZero */
+ true /* .isArray */
+}};
+
+/* DeleteReferencesResponse */
+static UA_DataTypeMember DeleteReferencesResponse_members[3] = {
+{
+ UA_TYPENAME("responseHeader") /* .memberName */
+ UA_TYPES_RESPONSEHEADER, /* .memberTypeIndex */
+ 0, /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("results") /* .memberName */
+ UA_TYPES_STATUSCODE, /* .memberTypeIndex */
+ offsetof(UA_DeleteReferencesResponse, resultsSize) - offsetof(UA_DeleteReferencesResponse, responseHeader) - sizeof(UA_ResponseHeader), /* .padding */
+ true, /* .namespaceZero */
+ true /* .isArray */
+},
+{
+ UA_TYPENAME("diagnosticInfos") /* .memberName */
+ UA_TYPES_DIAGNOSTICINFO, /* .memberTypeIndex */
+ offsetof(UA_DeleteReferencesResponse, diagnosticInfosSize) - offsetof(UA_DeleteReferencesResponse, results) - sizeof(void*), /* .padding */
+ true, /* .namespaceZero */
+ true /* .isArray */
+}};
+
+/* CreateMonitoredItemsResponse */
+static UA_DataTypeMember CreateMonitoredItemsResponse_members[3] = {
+{
+ UA_TYPENAME("responseHeader") /* .memberName */
+ UA_TYPES_RESPONSEHEADER, /* .memberTypeIndex */
+ 0, /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("results") /* .memberName */
+ UA_TYPES_MONITOREDITEMCREATERESULT, /* .memberTypeIndex */
+ offsetof(UA_CreateMonitoredItemsResponse, resultsSize) - offsetof(UA_CreateMonitoredItemsResponse, responseHeader) - sizeof(UA_ResponseHeader), /* .padding */
+ true, /* .namespaceZero */
+ true /* .isArray */
+},
+{
+ UA_TYPENAME("diagnosticInfos") /* .memberName */
+ UA_TYPES_DIAGNOSTICINFO, /* .memberTypeIndex */
+ offsetof(UA_CreateMonitoredItemsResponse, diagnosticInfosSize) - offsetof(UA_CreateMonitoredItemsResponse, results) - sizeof(void*), /* .padding */
+ true, /* .namespaceZero */
+ true /* .isArray */
+}};
+
+/* CallResponse */
+static UA_DataTypeMember CallResponse_members[3] = {
+{
+ UA_TYPENAME("responseHeader") /* .memberName */
+ UA_TYPES_RESPONSEHEADER, /* .memberTypeIndex */
+ 0, /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("results") /* .memberName */
+ UA_TYPES_CALLMETHODRESULT, /* .memberTypeIndex */
+ offsetof(UA_CallResponse, resultsSize) - offsetof(UA_CallResponse, responseHeader) - sizeof(UA_ResponseHeader), /* .padding */
+ true, /* .namespaceZero */
+ true /* .isArray */
+},
+{
+ UA_TYPENAME("diagnosticInfos") /* .memberName */
+ UA_TYPES_DIAGNOSTICINFO, /* .memberTypeIndex */
+ offsetof(UA_CallResponse, diagnosticInfosSize) - offsetof(UA_CallResponse, results) - sizeof(void*), /* .padding */
+ true, /* .namespaceZero */
+ true /* .isArray */
+}};
+
+/* DeleteNodesResponse */
+static UA_DataTypeMember DeleteNodesResponse_members[3] = {
+{
+ UA_TYPENAME("responseHeader") /* .memberName */
+ UA_TYPES_RESPONSEHEADER, /* .memberTypeIndex */
+ 0, /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("results") /* .memberName */
+ UA_TYPES_STATUSCODE, /* .memberTypeIndex */
+ offsetof(UA_DeleteNodesResponse, resultsSize) - offsetof(UA_DeleteNodesResponse, responseHeader) - sizeof(UA_ResponseHeader), /* .padding */
+ true, /* .namespaceZero */
+ true /* .isArray */
+},
+{
+ UA_TYPENAME("diagnosticInfos") /* .memberName */
+ UA_TYPES_DIAGNOSTICINFO, /* .memberTypeIndex */
+ offsetof(UA_DeleteNodesResponse, diagnosticInfosSize) - offsetof(UA_DeleteNodesResponse, results) - sizeof(void*), /* .padding */
+ true, /* .namespaceZero */
+ true /* .isArray */
+}};
+
+/* RepublishResponse */
+static UA_DataTypeMember RepublishResponse_members[2] = {
+{
+ UA_TYPENAME("responseHeader") /* .memberName */
+ UA_TYPES_RESPONSEHEADER, /* .memberTypeIndex */
+ 0, /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("notificationMessage") /* .memberName */
+ UA_TYPES_NOTIFICATIONMESSAGE, /* .memberTypeIndex */
+ offsetof(UA_RepublishResponse, notificationMessage) - offsetof(UA_RepublishResponse, responseHeader) - sizeof(UA_ResponseHeader), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+}};
+
+/* MonitoredItemCreateRequest */
+static UA_DataTypeMember MonitoredItemCreateRequest_members[3] = {
+{
+ UA_TYPENAME("itemToMonitor") /* .memberName */
+ UA_TYPES_READVALUEID, /* .memberTypeIndex */
+ 0, /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("monitoringMode") /* .memberName */
+ UA_TYPES_MONITORINGMODE, /* .memberTypeIndex */
+ offsetof(UA_MonitoredItemCreateRequest, monitoringMode) - offsetof(UA_MonitoredItemCreateRequest, itemToMonitor) - sizeof(UA_ReadValueId), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("requestedParameters") /* .memberName */
+ UA_TYPES_MONITORINGPARAMETERS, /* .memberTypeIndex */
+ offsetof(UA_MonitoredItemCreateRequest, requestedParameters) - offsetof(UA_MonitoredItemCreateRequest, monitoringMode) - sizeof(UA_MonitoringMode), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+}};
+
+/* DeleteReferencesRequest */
+static UA_DataTypeMember DeleteReferencesRequest_members[2] = {
+{
+ UA_TYPENAME("requestHeader") /* .memberName */
+ UA_TYPES_REQUESTHEADER, /* .memberTypeIndex */
+ 0, /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("referencesToDelete") /* .memberName */
+ UA_TYPES_DELETEREFERENCESITEM, /* .memberTypeIndex */
+ offsetof(UA_DeleteReferencesRequest, referencesToDeleteSize) - offsetof(UA_DeleteReferencesRequest, requestHeader) - sizeof(UA_RequestHeader), /* .padding */
+ true, /* .namespaceZero */
+ true /* .isArray */
+}};
+
+/* ReadResponse */
+static UA_DataTypeMember ReadResponse_members[3] = {
+{
+ UA_TYPENAME("responseHeader") /* .memberName */
+ UA_TYPES_RESPONSEHEADER, /* .memberTypeIndex */
+ 0, /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("results") /* .memberName */
+ UA_TYPES_DATAVALUE, /* .memberTypeIndex */
+ offsetof(UA_ReadResponse, resultsSize) - offsetof(UA_ReadResponse, responseHeader) - sizeof(UA_ResponseHeader), /* .padding */
+ true, /* .namespaceZero */
+ true /* .isArray */
+},
+{
+ UA_TYPENAME("diagnosticInfos") /* .memberName */
+ UA_TYPES_DIAGNOSTICINFO, /* .memberTypeIndex */
+ offsetof(UA_ReadResponse, diagnosticInfosSize) - offsetof(UA_ReadResponse, results) - sizeof(void*), /* .padding */
+ true, /* .namespaceZero */
+ true /* .isArray */
+}};
+
+/* AddReferencesRequest */
+static UA_DataTypeMember AddReferencesRequest_members[2] = {
+{
+ UA_TYPENAME("requestHeader") /* .memberName */
+ UA_TYPES_REQUESTHEADER, /* .memberTypeIndex */
+ 0, /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("referencesToAdd") /* .memberName */
+ UA_TYPES_ADDREFERENCESITEM, /* .memberTypeIndex */
+ offsetof(UA_AddReferencesRequest, referencesToAddSize) - offsetof(UA_AddReferencesRequest, requestHeader) - sizeof(UA_RequestHeader), /* .padding */
+ true, /* .namespaceZero */
+ true /* .isArray */
+}};
+
+/* ReadRequest */
+static UA_DataTypeMember ReadRequest_members[4] = {
+{
+ UA_TYPENAME("requestHeader") /* .memberName */
+ UA_TYPES_REQUESTHEADER, /* .memberTypeIndex */
+ 0, /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("maxAge") /* .memberName */
+ UA_TYPES_DOUBLE, /* .memberTypeIndex */
+ offsetof(UA_ReadRequest, maxAge) - offsetof(UA_ReadRequest, requestHeader) - sizeof(UA_RequestHeader), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("timestampsToReturn") /* .memberName */
+ UA_TYPES_TIMESTAMPSTORETURN, /* .memberTypeIndex */
+ offsetof(UA_ReadRequest, timestampsToReturn) - offsetof(UA_ReadRequest, maxAge) - sizeof(UA_Double), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("nodesToRead") /* .memberName */
+ UA_TYPES_READVALUEID, /* .memberTypeIndex */
+ offsetof(UA_ReadRequest, nodesToReadSize) - offsetof(UA_ReadRequest, timestampsToReturn) - sizeof(UA_TimestampsToReturn), /* .padding */
+ true, /* .namespaceZero */
+ true /* .isArray */
+}};
+
+/* OpenSecureChannelRequest */
+static UA_DataTypeMember OpenSecureChannelRequest_members[6] = {
+{
+ UA_TYPENAME("requestHeader") /* .memberName */
+ UA_TYPES_REQUESTHEADER, /* .memberTypeIndex */
+ 0, /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("clientProtocolVersion") /* .memberName */
+ UA_TYPES_UINT32, /* .memberTypeIndex */
+ offsetof(UA_OpenSecureChannelRequest, clientProtocolVersion) - offsetof(UA_OpenSecureChannelRequest, requestHeader) - sizeof(UA_RequestHeader), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("requestType") /* .memberName */
+ UA_TYPES_SECURITYTOKENREQUESTTYPE, /* .memberTypeIndex */
+ offsetof(UA_OpenSecureChannelRequest, requestType) - offsetof(UA_OpenSecureChannelRequest, clientProtocolVersion) - sizeof(UA_UInt32), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("securityMode") /* .memberName */
+ UA_TYPES_MESSAGESECURITYMODE, /* .memberTypeIndex */
+ offsetof(UA_OpenSecureChannelRequest, securityMode) - offsetof(UA_OpenSecureChannelRequest, requestType) - sizeof(UA_SecurityTokenRequestType), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("clientNonce") /* .memberName */
+ UA_TYPES_BYTESTRING, /* .memberTypeIndex */
+ offsetof(UA_OpenSecureChannelRequest, clientNonce) - offsetof(UA_OpenSecureChannelRequest, securityMode) - sizeof(UA_MessageSecurityMode), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("requestedLifetime") /* .memberName */
+ UA_TYPES_UINT32, /* .memberTypeIndex */
+ offsetof(UA_OpenSecureChannelRequest, requestedLifetime) - offsetof(UA_OpenSecureChannelRequest, clientNonce) - sizeof(UA_ByteString), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+}};
+
+/* RegisterServer2Response */
+static UA_DataTypeMember RegisterServer2Response_members[3] = {
+{
+ UA_TYPENAME("responseHeader") /* .memberName */
+ UA_TYPES_RESPONSEHEADER, /* .memberTypeIndex */
+ 0, /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("configurationResults") /* .memberName */
+ UA_TYPES_STATUSCODE, /* .memberTypeIndex */
+ offsetof(UA_RegisterServer2Response, configurationResultsSize) - offsetof(UA_RegisterServer2Response, responseHeader) - sizeof(UA_ResponseHeader), /* .padding */
+ true, /* .namespaceZero */
+ true /* .isArray */
+},
+{
+ UA_TYPENAME("diagnosticInfos") /* .memberName */
+ UA_TYPES_DIAGNOSTICINFO, /* .memberTypeIndex */
+ offsetof(UA_RegisterServer2Response, diagnosticInfosSize) - offsetof(UA_RegisterServer2Response, configurationResults) - sizeof(void*), /* .padding */
+ true, /* .namespaceZero */
+ true /* .isArray */
+}};
+
+/* AddNodesItem */
+static UA_DataTypeMember AddNodesItem_members[7] = {
+{
+ UA_TYPENAME("parentNodeId") /* .memberName */
+ UA_TYPES_EXPANDEDNODEID, /* .memberTypeIndex */
+ 0, /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("referenceTypeId") /* .memberName */
+ UA_TYPES_NODEID, /* .memberTypeIndex */
+ offsetof(UA_AddNodesItem, referenceTypeId) - offsetof(UA_AddNodesItem, parentNodeId) - sizeof(UA_ExpandedNodeId), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("requestedNewNodeId") /* .memberName */
+ UA_TYPES_EXPANDEDNODEID, /* .memberTypeIndex */
+ offsetof(UA_AddNodesItem, requestedNewNodeId) - offsetof(UA_AddNodesItem, referenceTypeId) - sizeof(UA_NodeId), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("browseName") /* .memberName */
+ UA_TYPES_QUALIFIEDNAME, /* .memberTypeIndex */
+ offsetof(UA_AddNodesItem, browseName) - offsetof(UA_AddNodesItem, requestedNewNodeId) - sizeof(UA_ExpandedNodeId), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("nodeClass") /* .memberName */
+ UA_TYPES_NODECLASS, /* .memberTypeIndex */
+ offsetof(UA_AddNodesItem, nodeClass) - offsetof(UA_AddNodesItem, browseName) - sizeof(UA_QualifiedName), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("nodeAttributes") /* .memberName */
+ UA_TYPES_EXTENSIONOBJECT, /* .memberTypeIndex */
+ offsetof(UA_AddNodesItem, nodeAttributes) - offsetof(UA_AddNodesItem, nodeClass) - sizeof(UA_NodeClass), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("typeDefinition") /* .memberName */
+ UA_TYPES_EXPANDEDNODEID, /* .memberTypeIndex */
+ offsetof(UA_AddNodesItem, typeDefinition) - offsetof(UA_AddNodesItem, nodeAttributes) - sizeof(UA_ExtensionObject), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+}};
+
+/* NodeTypeDescription */
+static UA_DataTypeMember NodeTypeDescription_members[3] = {
+{
+ UA_TYPENAME("typeDefinitionNode") /* .memberName */
+ UA_TYPES_EXPANDEDNODEID, /* .memberTypeIndex */
+ 0, /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("includeSubTypes") /* .memberName */
+ UA_TYPES_BOOLEAN, /* .memberTypeIndex */
+ offsetof(UA_NodeTypeDescription, includeSubTypes) - offsetof(UA_NodeTypeDescription, typeDefinitionNode) - sizeof(UA_ExpandedNodeId), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("dataToReturn") /* .memberName */
+ UA_TYPES_QUERYDATADESCRIPTION, /* .memberTypeIndex */
+ offsetof(UA_NodeTypeDescription, dataToReturnSize) - offsetof(UA_NodeTypeDescription, includeSubTypes) - sizeof(UA_Boolean), /* .padding */
+ true, /* .namespaceZero */
+ true /* .isArray */
+}};
+
+/* ServerStatusDataType */
+static UA_DataTypeMember ServerStatusDataType_members[6] = {
+{
+ UA_TYPENAME("startTime") /* .memberName */
+ UA_TYPES_DATETIME, /* .memberTypeIndex */
+ 0, /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("currentTime") /* .memberName */
+ UA_TYPES_DATETIME, /* .memberTypeIndex */
+ offsetof(UA_ServerStatusDataType, currentTime) - offsetof(UA_ServerStatusDataType, startTime) - sizeof(UA_DateTime), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("state") /* .memberName */
+ UA_TYPES_SERVERSTATE, /* .memberTypeIndex */
+ offsetof(UA_ServerStatusDataType, state) - offsetof(UA_ServerStatusDataType, currentTime) - sizeof(UA_DateTime), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("buildInfo") /* .memberName */
+ UA_TYPES_BUILDINFO, /* .memberTypeIndex */
+ offsetof(UA_ServerStatusDataType, buildInfo) - offsetof(UA_ServerStatusDataType, state) - sizeof(UA_ServerState), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("secondsTillShutdown") /* .memberName */
+ UA_TYPES_UINT32, /* .memberTypeIndex */
+ offsetof(UA_ServerStatusDataType, secondsTillShutdown) - offsetof(UA_ServerStatusDataType, buildInfo) - sizeof(UA_BuildInfo), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("shutdownReason") /* .memberName */
+ UA_TYPES_LOCALIZEDTEXT, /* .memberTypeIndex */
+ offsetof(UA_ServerStatusDataType, shutdownReason) - offsetof(UA_ServerStatusDataType, secondsTillShutdown) - sizeof(UA_UInt32), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+}};
+
+/* AttributeOperand */
+static UA_DataTypeMember AttributeOperand_members[5] = {
+{
+ UA_TYPENAME("nodeId") /* .memberName */
+ UA_TYPES_NODEID, /* .memberTypeIndex */
+ 0, /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("alias") /* .memberName */
+ UA_TYPES_STRING, /* .memberTypeIndex */
+ offsetof(UA_AttributeOperand, alias) - offsetof(UA_AttributeOperand, nodeId) - sizeof(UA_NodeId), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("browsePath") /* .memberName */
+ UA_TYPES_RELATIVEPATH, /* .memberTypeIndex */
+ offsetof(UA_AttributeOperand, browsePath) - offsetof(UA_AttributeOperand, alias) - sizeof(UA_String), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("attributeId") /* .memberName */
+ UA_TYPES_UINT32, /* .memberTypeIndex */
+ offsetof(UA_AttributeOperand, attributeId) - offsetof(UA_AttributeOperand, browsePath) - sizeof(UA_RelativePath), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("indexRange") /* .memberName */
+ UA_TYPES_STRING, /* .memberTypeIndex */
+ offsetof(UA_AttributeOperand, indexRange) - offsetof(UA_AttributeOperand, attributeId) - sizeof(UA_UInt32), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+}};
+
+/* AddReferencesResponse */
+static UA_DataTypeMember AddReferencesResponse_members[3] = {
+{
+ UA_TYPENAME("responseHeader") /* .memberName */
+ UA_TYPES_RESPONSEHEADER, /* .memberTypeIndex */
+ 0, /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("results") /* .memberName */
+ UA_TYPES_STATUSCODE, /* .memberTypeIndex */
+ offsetof(UA_AddReferencesResponse, resultsSize) - offsetof(UA_AddReferencesResponse, responseHeader) - sizeof(UA_ResponseHeader), /* .padding */
+ true, /* .namespaceZero */
+ true /* .isArray */
+},
+{
+ UA_TYPENAME("diagnosticInfos") /* .memberName */
+ UA_TYPES_DIAGNOSTICINFO, /* .memberTypeIndex */
+ offsetof(UA_AddReferencesResponse, diagnosticInfosSize) - offsetof(UA_AddReferencesResponse, results) - sizeof(void*), /* .padding */
+ true, /* .namespaceZero */
+ true /* .isArray */
+}};
+
+/* EventFilterResult */
+static UA_DataTypeMember EventFilterResult_members[3] = {
+{
+ UA_TYPENAME("selectClauseResults") /* .memberName */
+ UA_TYPES_STATUSCODE, /* .memberTypeIndex */
+ 0, /* .padding */
+ true, /* .namespaceZero */
+ true /* .isArray */
+},
+{
+ UA_TYPENAME("selectClauseDiagnosticInfos") /* .memberName */
+ UA_TYPES_DIAGNOSTICINFO, /* .memberTypeIndex */
+ offsetof(UA_EventFilterResult, selectClauseDiagnosticInfosSize) - offsetof(UA_EventFilterResult, selectClauseResults) - sizeof(void*), /* .padding */
+ true, /* .namespaceZero */
+ true /* .isArray */
+},
+{
+ UA_TYPENAME("whereClauseResult") /* .memberName */
+ UA_TYPES_CONTENTFILTERRESULT, /* .memberTypeIndex */
+ offsetof(UA_EventFilterResult, whereClauseResult) - offsetof(UA_EventFilterResult, selectClauseDiagnosticInfos) - sizeof(void*), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+}};
+
+/* TranslateBrowsePathsToNodeIdsResponse */
+static UA_DataTypeMember TranslateBrowsePathsToNodeIdsResponse_members[3] = {
+{
+ UA_TYPENAME("responseHeader") /* .memberName */
+ UA_TYPES_RESPONSEHEADER, /* .memberTypeIndex */
+ 0, /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("results") /* .memberName */
+ UA_TYPES_BROWSEPATHRESULT, /* .memberTypeIndex */
+ offsetof(UA_TranslateBrowsePathsToNodeIdsResponse, resultsSize) - offsetof(UA_TranslateBrowsePathsToNodeIdsResponse, responseHeader) - sizeof(UA_ResponseHeader), /* .padding */
+ true, /* .namespaceZero */
+ true /* .isArray */
+},
+{
+ UA_TYPENAME("diagnosticInfos") /* .memberName */
+ UA_TYPES_DIAGNOSTICINFO, /* .memberTypeIndex */
+ offsetof(UA_TranslateBrowsePathsToNodeIdsResponse, diagnosticInfosSize) - offsetof(UA_TranslateBrowsePathsToNodeIdsResponse, results) - sizeof(void*), /* .padding */
+ true, /* .namespaceZero */
+ true /* .isArray */
+}};
+
+/* DataChangeFilter */
+static UA_DataTypeMember DataChangeFilter_members[3] = {
+{
+ UA_TYPENAME("trigger") /* .memberName */
+ UA_TYPES_DATACHANGETRIGGER, /* .memberTypeIndex */
+ 0, /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("deadbandType") /* .memberName */
+ UA_TYPES_UINT32, /* .memberTypeIndex */
+ offsetof(UA_DataChangeFilter, deadbandType) - offsetof(UA_DataChangeFilter, trigger) - sizeof(UA_DataChangeTrigger), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("deadbandValue") /* .memberName */
+ UA_TYPES_DOUBLE, /* .memberTypeIndex */
+ offsetof(UA_DataChangeFilter, deadbandValue) - offsetof(UA_DataChangeFilter, deadbandType) - sizeof(UA_UInt32), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+}};
+
+/* ContentFilterElement */
+static UA_DataTypeMember ContentFilterElement_members[2] = {
+{
+ UA_TYPENAME("filterOperator") /* .memberName */
+ UA_TYPES_FILTEROPERATOR, /* .memberTypeIndex */
+ 0, /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("filterOperands") /* .memberName */
+ UA_TYPES_EXTENSIONOBJECT, /* .memberTypeIndex */
+ offsetof(UA_ContentFilterElement, filterOperandsSize) - offsetof(UA_ContentFilterElement, filterOperator) - sizeof(UA_FilterOperator), /* .padding */
+ true, /* .namespaceZero */
+ true /* .isArray */
+}};
+
+/* TranslateBrowsePathsToNodeIdsRequest */
+static UA_DataTypeMember TranslateBrowsePathsToNodeIdsRequest_members[2] = {
+{
+ UA_TYPENAME("requestHeader") /* .memberName */
+ UA_TYPES_REQUESTHEADER, /* .memberTypeIndex */
+ 0, /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("browsePaths") /* .memberName */
+ UA_TYPES_BROWSEPATH, /* .memberTypeIndex */
+ offsetof(UA_TranslateBrowsePathsToNodeIdsRequest, browsePathsSize) - offsetof(UA_TranslateBrowsePathsToNodeIdsRequest, requestHeader) - sizeof(UA_RequestHeader), /* .padding */
+ true, /* .namespaceZero */
+ true /* .isArray */
+}};
+
+/* CloseSessionResponse */
+static UA_DataTypeMember CloseSessionResponse_members[1] = {
+{
+ UA_TYPENAME("responseHeader") /* .memberName */
+ UA_TYPES_RESPONSEHEADER, /* .memberTypeIndex */
+ 0, /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+}};
+
+/* ApplicationDescription */
+static UA_DataTypeMember ApplicationDescription_members[7] = {
+{
+ UA_TYPENAME("applicationUri") /* .memberName */
+ UA_TYPES_STRING, /* .memberTypeIndex */
+ 0, /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("productUri") /* .memberName */
+ UA_TYPES_STRING, /* .memberTypeIndex */
+ offsetof(UA_ApplicationDescription, productUri) - offsetof(UA_ApplicationDescription, applicationUri) - sizeof(UA_String), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("applicationName") /* .memberName */
+ UA_TYPES_LOCALIZEDTEXT, /* .memberTypeIndex */
+ offsetof(UA_ApplicationDescription, applicationName) - offsetof(UA_ApplicationDescription, productUri) - sizeof(UA_String), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("applicationType") /* .memberName */
+ UA_TYPES_APPLICATIONTYPE, /* .memberTypeIndex */
+ offsetof(UA_ApplicationDescription, applicationType) - offsetof(UA_ApplicationDescription, applicationName) - sizeof(UA_LocalizedText), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("gatewayServerUri") /* .memberName */
+ UA_TYPES_STRING, /* .memberTypeIndex */
+ offsetof(UA_ApplicationDescription, gatewayServerUri) - offsetof(UA_ApplicationDescription, applicationType) - sizeof(UA_ApplicationType), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("discoveryProfileUri") /* .memberName */
+ UA_TYPES_STRING, /* .memberTypeIndex */
+ offsetof(UA_ApplicationDescription, discoveryProfileUri) - offsetof(UA_ApplicationDescription, gatewayServerUri) - sizeof(UA_String), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("discoveryUrls") /* .memberName */
+ UA_TYPES_STRING, /* .memberTypeIndex */
+ offsetof(UA_ApplicationDescription, discoveryUrlsSize) - offsetof(UA_ApplicationDescription, discoveryProfileUri) - sizeof(UA_String), /* .padding */
+ true, /* .namespaceZero */
+ true /* .isArray */
+}};
+
+/* SessionDiagnosticsDataType */
+static UA_DataTypeMember SessionDiagnosticsDataType_members[43] = {
+{
+ UA_TYPENAME("sessionId") /* .memberName */
+ UA_TYPES_NODEID, /* .memberTypeIndex */
+ 0, /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("sessionName") /* .memberName */
+ UA_TYPES_STRING, /* .memberTypeIndex */
+ offsetof(UA_SessionDiagnosticsDataType, sessionName) - offsetof(UA_SessionDiagnosticsDataType, sessionId) - sizeof(UA_NodeId), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("clientDescription") /* .memberName */
+ UA_TYPES_APPLICATIONDESCRIPTION, /* .memberTypeIndex */
+ offsetof(UA_SessionDiagnosticsDataType, clientDescription) - offsetof(UA_SessionDiagnosticsDataType, sessionName) - sizeof(UA_String), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("serverUri") /* .memberName */
+ UA_TYPES_STRING, /* .memberTypeIndex */
+ offsetof(UA_SessionDiagnosticsDataType, serverUri) - offsetof(UA_SessionDiagnosticsDataType, clientDescription) - sizeof(UA_ApplicationDescription), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("endpointUrl") /* .memberName */
+ UA_TYPES_STRING, /* .memberTypeIndex */
+ offsetof(UA_SessionDiagnosticsDataType, endpointUrl) - offsetof(UA_SessionDiagnosticsDataType, serverUri) - sizeof(UA_String), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("localeIds") /* .memberName */
+ UA_TYPES_STRING, /* .memberTypeIndex */
+ offsetof(UA_SessionDiagnosticsDataType, localeIdsSize) - offsetof(UA_SessionDiagnosticsDataType, endpointUrl) - sizeof(UA_String), /* .padding */
+ true, /* .namespaceZero */
+ true /* .isArray */
+},
+{
+ UA_TYPENAME("actualSessionTimeout") /* .memberName */
+ UA_TYPES_DOUBLE, /* .memberTypeIndex */
+ offsetof(UA_SessionDiagnosticsDataType, actualSessionTimeout) - offsetof(UA_SessionDiagnosticsDataType, localeIds) - sizeof(void*), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("maxResponseMessageSize") /* .memberName */
+ UA_TYPES_UINT32, /* .memberTypeIndex */
+ offsetof(UA_SessionDiagnosticsDataType, maxResponseMessageSize) - offsetof(UA_SessionDiagnosticsDataType, actualSessionTimeout) - sizeof(UA_Double), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("clientConnectionTime") /* .memberName */
+ UA_TYPES_DATETIME, /* .memberTypeIndex */
+ offsetof(UA_SessionDiagnosticsDataType, clientConnectionTime) - offsetof(UA_SessionDiagnosticsDataType, maxResponseMessageSize) - sizeof(UA_UInt32), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("clientLastContactTime") /* .memberName */
+ UA_TYPES_DATETIME, /* .memberTypeIndex */
+ offsetof(UA_SessionDiagnosticsDataType, clientLastContactTime) - offsetof(UA_SessionDiagnosticsDataType, clientConnectionTime) - sizeof(UA_DateTime), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("currentSubscriptionsCount") /* .memberName */
+ UA_TYPES_UINT32, /* .memberTypeIndex */
+ offsetof(UA_SessionDiagnosticsDataType, currentSubscriptionsCount) - offsetof(UA_SessionDiagnosticsDataType, clientLastContactTime) - sizeof(UA_DateTime), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("currentMonitoredItemsCount") /* .memberName */
+ UA_TYPES_UINT32, /* .memberTypeIndex */
+ offsetof(UA_SessionDiagnosticsDataType, currentMonitoredItemsCount) - offsetof(UA_SessionDiagnosticsDataType, currentSubscriptionsCount) - sizeof(UA_UInt32), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("currentPublishRequestsInQueue") /* .memberName */
+ UA_TYPES_UINT32, /* .memberTypeIndex */
+ offsetof(UA_SessionDiagnosticsDataType, currentPublishRequestsInQueue) - offsetof(UA_SessionDiagnosticsDataType, currentMonitoredItemsCount) - sizeof(UA_UInt32), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("totalRequestCount") /* .memberName */
+ UA_TYPES_SERVICECOUNTERDATATYPE, /* .memberTypeIndex */
+ offsetof(UA_SessionDiagnosticsDataType, totalRequestCount) - offsetof(UA_SessionDiagnosticsDataType, currentPublishRequestsInQueue) - sizeof(UA_UInt32), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("unauthorizedRequestCount") /* .memberName */
+ UA_TYPES_UINT32, /* .memberTypeIndex */
+ offsetof(UA_SessionDiagnosticsDataType, unauthorizedRequestCount) - offsetof(UA_SessionDiagnosticsDataType, totalRequestCount) - sizeof(UA_ServiceCounterDataType), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("readCount") /* .memberName */
+ UA_TYPES_SERVICECOUNTERDATATYPE, /* .memberTypeIndex */
+ offsetof(UA_SessionDiagnosticsDataType, readCount) - offsetof(UA_SessionDiagnosticsDataType, unauthorizedRequestCount) - sizeof(UA_UInt32), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("historyReadCount") /* .memberName */
+ UA_TYPES_SERVICECOUNTERDATATYPE, /* .memberTypeIndex */
+ offsetof(UA_SessionDiagnosticsDataType, historyReadCount) - offsetof(UA_SessionDiagnosticsDataType, readCount) - sizeof(UA_ServiceCounterDataType), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("writeCount") /* .memberName */
+ UA_TYPES_SERVICECOUNTERDATATYPE, /* .memberTypeIndex */
+ offsetof(UA_SessionDiagnosticsDataType, writeCount) - offsetof(UA_SessionDiagnosticsDataType, historyReadCount) - sizeof(UA_ServiceCounterDataType), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("historyUpdateCount") /* .memberName */
+ UA_TYPES_SERVICECOUNTERDATATYPE, /* .memberTypeIndex */
+ offsetof(UA_SessionDiagnosticsDataType, historyUpdateCount) - offsetof(UA_SessionDiagnosticsDataType, writeCount) - sizeof(UA_ServiceCounterDataType), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("callCount") /* .memberName */
+ UA_TYPES_SERVICECOUNTERDATATYPE, /* .memberTypeIndex */
+ offsetof(UA_SessionDiagnosticsDataType, callCount) - offsetof(UA_SessionDiagnosticsDataType, historyUpdateCount) - sizeof(UA_ServiceCounterDataType), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("createMonitoredItemsCount") /* .memberName */
+ UA_TYPES_SERVICECOUNTERDATATYPE, /* .memberTypeIndex */
+ offsetof(UA_SessionDiagnosticsDataType, createMonitoredItemsCount) - offsetof(UA_SessionDiagnosticsDataType, callCount) - sizeof(UA_ServiceCounterDataType), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("modifyMonitoredItemsCount") /* .memberName */
+ UA_TYPES_SERVICECOUNTERDATATYPE, /* .memberTypeIndex */
+ offsetof(UA_SessionDiagnosticsDataType, modifyMonitoredItemsCount) - offsetof(UA_SessionDiagnosticsDataType, createMonitoredItemsCount) - sizeof(UA_ServiceCounterDataType), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("setMonitoringModeCount") /* .memberName */
+ UA_TYPES_SERVICECOUNTERDATATYPE, /* .memberTypeIndex */
+ offsetof(UA_SessionDiagnosticsDataType, setMonitoringModeCount) - offsetof(UA_SessionDiagnosticsDataType, modifyMonitoredItemsCount) - sizeof(UA_ServiceCounterDataType), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("setTriggeringCount") /* .memberName */
+ UA_TYPES_SERVICECOUNTERDATATYPE, /* .memberTypeIndex */
+ offsetof(UA_SessionDiagnosticsDataType, setTriggeringCount) - offsetof(UA_SessionDiagnosticsDataType, setMonitoringModeCount) - sizeof(UA_ServiceCounterDataType), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("deleteMonitoredItemsCount") /* .memberName */
+ UA_TYPES_SERVICECOUNTERDATATYPE, /* .memberTypeIndex */
+ offsetof(UA_SessionDiagnosticsDataType, deleteMonitoredItemsCount) - offsetof(UA_SessionDiagnosticsDataType, setTriggeringCount) - sizeof(UA_ServiceCounterDataType), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("createSubscriptionCount") /* .memberName */
+ UA_TYPES_SERVICECOUNTERDATATYPE, /* .memberTypeIndex */
+ offsetof(UA_SessionDiagnosticsDataType, createSubscriptionCount) - offsetof(UA_SessionDiagnosticsDataType, deleteMonitoredItemsCount) - sizeof(UA_ServiceCounterDataType), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("modifySubscriptionCount") /* .memberName */
+ UA_TYPES_SERVICECOUNTERDATATYPE, /* .memberTypeIndex */
+ offsetof(UA_SessionDiagnosticsDataType, modifySubscriptionCount) - offsetof(UA_SessionDiagnosticsDataType, createSubscriptionCount) - sizeof(UA_ServiceCounterDataType), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("setPublishingModeCount") /* .memberName */
+ UA_TYPES_SERVICECOUNTERDATATYPE, /* .memberTypeIndex */
+ offsetof(UA_SessionDiagnosticsDataType, setPublishingModeCount) - offsetof(UA_SessionDiagnosticsDataType, modifySubscriptionCount) - sizeof(UA_ServiceCounterDataType), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("publishCount") /* .memberName */
+ UA_TYPES_SERVICECOUNTERDATATYPE, /* .memberTypeIndex */
+ offsetof(UA_SessionDiagnosticsDataType, publishCount) - offsetof(UA_SessionDiagnosticsDataType, setPublishingModeCount) - sizeof(UA_ServiceCounterDataType), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("republishCount") /* .memberName */
+ UA_TYPES_SERVICECOUNTERDATATYPE, /* .memberTypeIndex */
+ offsetof(UA_SessionDiagnosticsDataType, republishCount) - offsetof(UA_SessionDiagnosticsDataType, publishCount) - sizeof(UA_ServiceCounterDataType), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("transferSubscriptionsCount") /* .memberName */
+ UA_TYPES_SERVICECOUNTERDATATYPE, /* .memberTypeIndex */
+ offsetof(UA_SessionDiagnosticsDataType, transferSubscriptionsCount) - offsetof(UA_SessionDiagnosticsDataType, republishCount) - sizeof(UA_ServiceCounterDataType), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("deleteSubscriptionsCount") /* .memberName */
+ UA_TYPES_SERVICECOUNTERDATATYPE, /* .memberTypeIndex */
+ offsetof(UA_SessionDiagnosticsDataType, deleteSubscriptionsCount) - offsetof(UA_SessionDiagnosticsDataType, transferSubscriptionsCount) - sizeof(UA_ServiceCounterDataType), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("addNodesCount") /* .memberName */
+ UA_TYPES_SERVICECOUNTERDATATYPE, /* .memberTypeIndex */
+ offsetof(UA_SessionDiagnosticsDataType, addNodesCount) - offsetof(UA_SessionDiagnosticsDataType, deleteSubscriptionsCount) - sizeof(UA_ServiceCounterDataType), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("addReferencesCount") /* .memberName */
+ UA_TYPES_SERVICECOUNTERDATATYPE, /* .memberTypeIndex */
+ offsetof(UA_SessionDiagnosticsDataType, addReferencesCount) - offsetof(UA_SessionDiagnosticsDataType, addNodesCount) - sizeof(UA_ServiceCounterDataType), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("deleteNodesCount") /* .memberName */
+ UA_TYPES_SERVICECOUNTERDATATYPE, /* .memberTypeIndex */
+ offsetof(UA_SessionDiagnosticsDataType, deleteNodesCount) - offsetof(UA_SessionDiagnosticsDataType, addReferencesCount) - sizeof(UA_ServiceCounterDataType), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("deleteReferencesCount") /* .memberName */
+ UA_TYPES_SERVICECOUNTERDATATYPE, /* .memberTypeIndex */
+ offsetof(UA_SessionDiagnosticsDataType, deleteReferencesCount) - offsetof(UA_SessionDiagnosticsDataType, deleteNodesCount) - sizeof(UA_ServiceCounterDataType), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("browseCount") /* .memberName */
+ UA_TYPES_SERVICECOUNTERDATATYPE, /* .memberTypeIndex */
+ offsetof(UA_SessionDiagnosticsDataType, browseCount) - offsetof(UA_SessionDiagnosticsDataType, deleteReferencesCount) - sizeof(UA_ServiceCounterDataType), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("browseNextCount") /* .memberName */
+ UA_TYPES_SERVICECOUNTERDATATYPE, /* .memberTypeIndex */
+ offsetof(UA_SessionDiagnosticsDataType, browseNextCount) - offsetof(UA_SessionDiagnosticsDataType, browseCount) - sizeof(UA_ServiceCounterDataType), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("translateBrowsePathsToNodeIdsCount") /* .memberName */
+ UA_TYPES_SERVICECOUNTERDATATYPE, /* .memberTypeIndex */
+ offsetof(UA_SessionDiagnosticsDataType, translateBrowsePathsToNodeIdsCount) - offsetof(UA_SessionDiagnosticsDataType, browseNextCount) - sizeof(UA_ServiceCounterDataType), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("queryFirstCount") /* .memberName */
+ UA_TYPES_SERVICECOUNTERDATATYPE, /* .memberTypeIndex */
+ offsetof(UA_SessionDiagnosticsDataType, queryFirstCount) - offsetof(UA_SessionDiagnosticsDataType, translateBrowsePathsToNodeIdsCount) - sizeof(UA_ServiceCounterDataType), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("queryNextCount") /* .memberName */
+ UA_TYPES_SERVICECOUNTERDATATYPE, /* .memberTypeIndex */
+ offsetof(UA_SessionDiagnosticsDataType, queryNextCount) - offsetof(UA_SessionDiagnosticsDataType, queryFirstCount) - sizeof(UA_ServiceCounterDataType), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("registerNodesCount") /* .memberName */
+ UA_TYPES_SERVICECOUNTERDATATYPE, /* .memberTypeIndex */
+ offsetof(UA_SessionDiagnosticsDataType, registerNodesCount) - offsetof(UA_SessionDiagnosticsDataType, queryNextCount) - sizeof(UA_ServiceCounterDataType), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("unregisterNodesCount") /* .memberName */
+ UA_TYPES_SERVICECOUNTERDATATYPE, /* .memberTypeIndex */
+ offsetof(UA_SessionDiagnosticsDataType, unregisterNodesCount) - offsetof(UA_SessionDiagnosticsDataType, registerNodesCount) - sizeof(UA_ServiceCounterDataType), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+}};
+
+/* ServiceFault */
+static UA_DataTypeMember ServiceFault_members[1] = {
+{
+ UA_TYPENAME("responseHeader") /* .memberName */
+ UA_TYPES_RESPONSEHEADER, /* .memberTypeIndex */
+ 0, /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+}};
+
+/* RegisteredServer */
+static UA_DataTypeMember RegisteredServer_members[8] = {
+{
+ UA_TYPENAME("serverUri") /* .memberName */
+ UA_TYPES_STRING, /* .memberTypeIndex */
+ 0, /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("productUri") /* .memberName */
+ UA_TYPES_STRING, /* .memberTypeIndex */
+ offsetof(UA_RegisteredServer, productUri) - offsetof(UA_RegisteredServer, serverUri) - sizeof(UA_String), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("serverNames") /* .memberName */
+ UA_TYPES_LOCALIZEDTEXT, /* .memberTypeIndex */
+ offsetof(UA_RegisteredServer, serverNamesSize) - offsetof(UA_RegisteredServer, productUri) - sizeof(UA_String), /* .padding */
+ true, /* .namespaceZero */
+ true /* .isArray */
+},
+{
+ UA_TYPENAME("serverType") /* .memberName */
+ UA_TYPES_APPLICATIONTYPE, /* .memberTypeIndex */
+ offsetof(UA_RegisteredServer, serverType) - offsetof(UA_RegisteredServer, serverNames) - sizeof(void*), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("gatewayServerUri") /* .memberName */
+ UA_TYPES_STRING, /* .memberTypeIndex */
+ offsetof(UA_RegisteredServer, gatewayServerUri) - offsetof(UA_RegisteredServer, serverType) - sizeof(UA_ApplicationType), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("discoveryUrls") /* .memberName */
+ UA_TYPES_STRING, /* .memberTypeIndex */
+ offsetof(UA_RegisteredServer, discoveryUrlsSize) - offsetof(UA_RegisteredServer, gatewayServerUri) - sizeof(UA_String), /* .padding */
+ true, /* .namespaceZero */
+ true /* .isArray */
+},
+{
+ UA_TYPENAME("semaphoreFilePath") /* .memberName */
+ UA_TYPES_STRING, /* .memberTypeIndex */
+ offsetof(UA_RegisteredServer, semaphoreFilePath) - offsetof(UA_RegisteredServer, discoveryUrls) - sizeof(void*), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("isOnline") /* .memberName */
+ UA_TYPES_BOOLEAN, /* .memberTypeIndex */
+ offsetof(UA_RegisteredServer, isOnline) - offsetof(UA_RegisteredServer, semaphoreFilePath) - sizeof(UA_String), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+}};
+
+/* AggregateFilter */
+static UA_DataTypeMember AggregateFilter_members[4] = {
+{
+ UA_TYPENAME("startTime") /* .memberName */
+ UA_TYPES_DATETIME, /* .memberTypeIndex */
+ 0, /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("aggregateType") /* .memberName */
+ UA_TYPES_NODEID, /* .memberTypeIndex */
+ offsetof(UA_AggregateFilter, aggregateType) - offsetof(UA_AggregateFilter, startTime) - sizeof(UA_DateTime), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("processingInterval") /* .memberName */
+ UA_TYPES_DOUBLE, /* .memberTypeIndex */
+ offsetof(UA_AggregateFilter, processingInterval) - offsetof(UA_AggregateFilter, aggregateType) - sizeof(UA_NodeId), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("aggregateConfiguration") /* .memberName */
+ UA_TYPES_AGGREGATECONFIGURATION, /* .memberTypeIndex */
+ offsetof(UA_AggregateFilter, aggregateConfiguration) - offsetof(UA_AggregateFilter, processingInterval) - sizeof(UA_Double), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+}};
+
+/* RegisterServerRequest */
+static UA_DataTypeMember RegisterServerRequest_members[2] = {
+{
+ UA_TYPENAME("requestHeader") /* .memberName */
+ UA_TYPES_REQUESTHEADER, /* .memberTypeIndex */
+ 0, /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("server") /* .memberName */
+ UA_TYPES_REGISTEREDSERVER, /* .memberTypeIndex */
+ offsetof(UA_RegisterServerRequest, server) - offsetof(UA_RegisterServerRequest, requestHeader) - sizeof(UA_RequestHeader), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+}};
+
+/* EndpointDescription */
+static UA_DataTypeMember EndpointDescription_members[8] = {
+{
+ UA_TYPENAME("endpointUrl") /* .memberName */
+ UA_TYPES_STRING, /* .memberTypeIndex */
+ 0, /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("server") /* .memberName */
+ UA_TYPES_APPLICATIONDESCRIPTION, /* .memberTypeIndex */
+ offsetof(UA_EndpointDescription, server) - offsetof(UA_EndpointDescription, endpointUrl) - sizeof(UA_String), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("serverCertificate") /* .memberName */
+ UA_TYPES_BYTESTRING, /* .memberTypeIndex */
+ offsetof(UA_EndpointDescription, serverCertificate) - offsetof(UA_EndpointDescription, server) - sizeof(UA_ApplicationDescription), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("securityMode") /* .memberName */
+ UA_TYPES_MESSAGESECURITYMODE, /* .memberTypeIndex */
+ offsetof(UA_EndpointDescription, securityMode) - offsetof(UA_EndpointDescription, serverCertificate) - sizeof(UA_ByteString), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("securityPolicyUri") /* .memberName */
+ UA_TYPES_STRING, /* .memberTypeIndex */
+ offsetof(UA_EndpointDescription, securityPolicyUri) - offsetof(UA_EndpointDescription, securityMode) - sizeof(UA_MessageSecurityMode), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("userIdentityTokens") /* .memberName */
+ UA_TYPES_USERTOKENPOLICY, /* .memberTypeIndex */
+ offsetof(UA_EndpointDescription, userIdentityTokensSize) - offsetof(UA_EndpointDescription, securityPolicyUri) - sizeof(UA_String), /* .padding */
+ true, /* .namespaceZero */
+ true /* .isArray */
+},
+{
+ UA_TYPENAME("transportProfileUri") /* .memberName */
+ UA_TYPES_STRING, /* .memberTypeIndex */
+ offsetof(UA_EndpointDescription, transportProfileUri) - offsetof(UA_EndpointDescription, userIdentityTokens) - sizeof(void*), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("securityLevel") /* .memberName */
+ UA_TYPES_BYTE, /* .memberTypeIndex */
+ offsetof(UA_EndpointDescription, securityLevel) - offsetof(UA_EndpointDescription, transportProfileUri) - sizeof(UA_String), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+}};
+
+/* CreateMonitoredItemsRequest */
+static UA_DataTypeMember CreateMonitoredItemsRequest_members[4] = {
+{
+ UA_TYPENAME("requestHeader") /* .memberName */
+ UA_TYPES_REQUESTHEADER, /* .memberTypeIndex */
+ 0, /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("subscriptionId") /* .memberName */
+ UA_TYPES_UINT32, /* .memberTypeIndex */
+ offsetof(UA_CreateMonitoredItemsRequest, subscriptionId) - offsetof(UA_CreateMonitoredItemsRequest, requestHeader) - sizeof(UA_RequestHeader), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("timestampsToReturn") /* .memberName */
+ UA_TYPES_TIMESTAMPSTORETURN, /* .memberTypeIndex */
+ offsetof(UA_CreateMonitoredItemsRequest, timestampsToReturn) - offsetof(UA_CreateMonitoredItemsRequest, subscriptionId) - sizeof(UA_UInt32), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("itemsToCreate") /* .memberName */
+ UA_TYPES_MONITOREDITEMCREATEREQUEST, /* .memberTypeIndex */
+ offsetof(UA_CreateMonitoredItemsRequest, itemsToCreateSize) - offsetof(UA_CreateMonitoredItemsRequest, timestampsToReturn) - sizeof(UA_TimestampsToReturn), /* .padding */
+ true, /* .namespaceZero */
+ true /* .isArray */
+}};
+
+/* ContentFilter */
+static UA_DataTypeMember ContentFilter_members[1] = {
+{
+ UA_TYPENAME("elements") /* .memberName */
+ UA_TYPES_CONTENTFILTERELEMENT, /* .memberTypeIndex */
+ 0, /* .padding */
+ true, /* .namespaceZero */
+ true /* .isArray */
+}};
+
+/* QueryFirstResponse */
+static UA_DataTypeMember QueryFirstResponse_members[6] = {
+{
+ UA_TYPENAME("responseHeader") /* .memberName */
+ UA_TYPES_RESPONSEHEADER, /* .memberTypeIndex */
+ 0, /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("queryDataSets") /* .memberName */
+ UA_TYPES_QUERYDATASET, /* .memberTypeIndex */
+ offsetof(UA_QueryFirstResponse, queryDataSetsSize) - offsetof(UA_QueryFirstResponse, responseHeader) - sizeof(UA_ResponseHeader), /* .padding */
+ true, /* .namespaceZero */
+ true /* .isArray */
+},
+{
+ UA_TYPENAME("continuationPoint") /* .memberName */
+ UA_TYPES_BYTESTRING, /* .memberTypeIndex */
+ offsetof(UA_QueryFirstResponse, continuationPoint) - offsetof(UA_QueryFirstResponse, queryDataSets) - sizeof(void*), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("parsingResults") /* .memberName */
+ UA_TYPES_PARSINGRESULT, /* .memberTypeIndex */
+ offsetof(UA_QueryFirstResponse, parsingResultsSize) - offsetof(UA_QueryFirstResponse, continuationPoint) - sizeof(UA_ByteString), /* .padding */
+ true, /* .namespaceZero */
+ true /* .isArray */
+},
+{
+ UA_TYPENAME("diagnosticInfos") /* .memberName */
+ UA_TYPES_DIAGNOSTICINFO, /* .memberTypeIndex */
+ offsetof(UA_QueryFirstResponse, diagnosticInfosSize) - offsetof(UA_QueryFirstResponse, parsingResults) - sizeof(void*), /* .padding */
+ true, /* .namespaceZero */
+ true /* .isArray */
+},
+{
+ UA_TYPENAME("filterResult") /* .memberName */
+ UA_TYPES_CONTENTFILTERRESULT, /* .memberTypeIndex */
+ offsetof(UA_QueryFirstResponse, filterResult) - offsetof(UA_QueryFirstResponse, diagnosticInfos) - sizeof(void*), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+}};
+
+/* AddNodesRequest */
+static UA_DataTypeMember AddNodesRequest_members[2] = {
+{
+ UA_TYPENAME("requestHeader") /* .memberName */
+ UA_TYPES_REQUESTHEADER, /* .memberTypeIndex */
+ 0, /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("nodesToAdd") /* .memberName */
+ UA_TYPES_ADDNODESITEM, /* .memberTypeIndex */
+ offsetof(UA_AddNodesRequest, nodesToAddSize) - offsetof(UA_AddNodesRequest, requestHeader) - sizeof(UA_RequestHeader), /* .padding */
+ true, /* .namespaceZero */
+ true /* .isArray */
+}};
+
+/* BrowseRequest */
+static UA_DataTypeMember BrowseRequest_members[4] = {
+{
+ UA_TYPENAME("requestHeader") /* .memberName */
+ UA_TYPES_REQUESTHEADER, /* .memberTypeIndex */
+ 0, /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("view") /* .memberName */
+ UA_TYPES_VIEWDESCRIPTION, /* .memberTypeIndex */
+ offsetof(UA_BrowseRequest, view) - offsetof(UA_BrowseRequest, requestHeader) - sizeof(UA_RequestHeader), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("requestedMaxReferencesPerNode") /* .memberName */
+ UA_TYPES_UINT32, /* .memberTypeIndex */
+ offsetof(UA_BrowseRequest, requestedMaxReferencesPerNode) - offsetof(UA_BrowseRequest, view) - sizeof(UA_ViewDescription), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("nodesToBrowse") /* .memberName */
+ UA_TYPES_BROWSEDESCRIPTION, /* .memberTypeIndex */
+ offsetof(UA_BrowseRequest, nodesToBrowseSize) - offsetof(UA_BrowseRequest, requestedMaxReferencesPerNode) - sizeof(UA_UInt32), /* .padding */
+ true, /* .namespaceZero */
+ true /* .isArray */
+}};
+
+/* BrowseResult */
+static UA_DataTypeMember BrowseResult_members[3] = {
+{
+ UA_TYPENAME("statusCode") /* .memberName */
+ UA_TYPES_STATUSCODE, /* .memberTypeIndex */
+ 0, /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("continuationPoint") /* .memberName */
+ UA_TYPES_BYTESTRING, /* .memberTypeIndex */
+ offsetof(UA_BrowseResult, continuationPoint) - offsetof(UA_BrowseResult, statusCode) - sizeof(UA_StatusCode), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("references") /* .memberName */
+ UA_TYPES_REFERENCEDESCRIPTION, /* .memberTypeIndex */
+ offsetof(UA_BrowseResult, referencesSize) - offsetof(UA_BrowseResult, continuationPoint) - sizeof(UA_ByteString), /* .padding */
+ true, /* .namespaceZero */
+ true /* .isArray */
+}};
+
+/* RegisterServer2Request */
+static UA_DataTypeMember RegisterServer2Request_members[3] = {
+{
+ UA_TYPENAME("requestHeader") /* .memberName */
+ UA_TYPES_REQUESTHEADER, /* .memberTypeIndex */
+ 0, /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("server") /* .memberName */
+ UA_TYPES_REGISTEREDSERVER, /* .memberTypeIndex */
+ offsetof(UA_RegisterServer2Request, server) - offsetof(UA_RegisterServer2Request, requestHeader) - sizeof(UA_RequestHeader), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("discoveryConfiguration") /* .memberName */
+ UA_TYPES_EXTENSIONOBJECT, /* .memberTypeIndex */
+ offsetof(UA_RegisterServer2Request, discoveryConfigurationSize) - offsetof(UA_RegisterServer2Request, server) - sizeof(UA_RegisteredServer), /* .padding */
+ true, /* .namespaceZero */
+ true /* .isArray */
+}};
+
+/* CreateSessionRequest */
+static UA_DataTypeMember CreateSessionRequest_members[9] = {
+{
+ UA_TYPENAME("requestHeader") /* .memberName */
+ UA_TYPES_REQUESTHEADER, /* .memberTypeIndex */
+ 0, /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("clientDescription") /* .memberName */
+ UA_TYPES_APPLICATIONDESCRIPTION, /* .memberTypeIndex */
+ offsetof(UA_CreateSessionRequest, clientDescription) - offsetof(UA_CreateSessionRequest, requestHeader) - sizeof(UA_RequestHeader), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("serverUri") /* .memberName */
+ UA_TYPES_STRING, /* .memberTypeIndex */
+ offsetof(UA_CreateSessionRequest, serverUri) - offsetof(UA_CreateSessionRequest, clientDescription) - sizeof(UA_ApplicationDescription), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("endpointUrl") /* .memberName */
+ UA_TYPES_STRING, /* .memberTypeIndex */
+ offsetof(UA_CreateSessionRequest, endpointUrl) - offsetof(UA_CreateSessionRequest, serverUri) - sizeof(UA_String), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("sessionName") /* .memberName */
+ UA_TYPES_STRING, /* .memberTypeIndex */
+ offsetof(UA_CreateSessionRequest, sessionName) - offsetof(UA_CreateSessionRequest, endpointUrl) - sizeof(UA_String), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("clientNonce") /* .memberName */
+ UA_TYPES_BYTESTRING, /* .memberTypeIndex */
+ offsetof(UA_CreateSessionRequest, clientNonce) - offsetof(UA_CreateSessionRequest, sessionName) - sizeof(UA_String), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("clientCertificate") /* .memberName */
+ UA_TYPES_BYTESTRING, /* .memberTypeIndex */
+ offsetof(UA_CreateSessionRequest, clientCertificate) - offsetof(UA_CreateSessionRequest, clientNonce) - sizeof(UA_ByteString), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("requestedSessionTimeout") /* .memberName */
+ UA_TYPES_DOUBLE, /* .memberTypeIndex */
+ offsetof(UA_CreateSessionRequest, requestedSessionTimeout) - offsetof(UA_CreateSessionRequest, clientCertificate) - sizeof(UA_ByteString), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("maxResponseMessageSize") /* .memberName */
+ UA_TYPES_UINT32, /* .memberTypeIndex */
+ offsetof(UA_CreateSessionRequest, maxResponseMessageSize) - offsetof(UA_CreateSessionRequest, requestedSessionTimeout) - sizeof(UA_Double), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+}};
+
+/* EventFilter */
+static UA_DataTypeMember EventFilter_members[2] = {
+{
+ UA_TYPENAME("selectClauses") /* .memberName */
+ UA_TYPES_SIMPLEATTRIBUTEOPERAND, /* .memberTypeIndex */
+ 0, /* .padding */
+ true, /* .namespaceZero */
+ true /* .isArray */
+},
+{
+ UA_TYPENAME("whereClause") /* .memberName */
+ UA_TYPES_CONTENTFILTER, /* .memberTypeIndex */
+ offsetof(UA_EventFilter, whereClause) - offsetof(UA_EventFilter, selectClauses) - sizeof(void*), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+}};
+
+/* GetEndpointsResponse */
+static UA_DataTypeMember GetEndpointsResponse_members[2] = {
+{
+ UA_TYPENAME("responseHeader") /* .memberName */
+ UA_TYPES_RESPONSEHEADER, /* .memberTypeIndex */
+ 0, /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("endpoints") /* .memberName */
+ UA_TYPES_ENDPOINTDESCRIPTION, /* .memberTypeIndex */
+ offsetof(UA_GetEndpointsResponse, endpointsSize) - offsetof(UA_GetEndpointsResponse, responseHeader) - sizeof(UA_ResponseHeader), /* .padding */
+ true, /* .namespaceZero */
+ true /* .isArray */
+}};
+
+/* FindServersResponse */
+static UA_DataTypeMember FindServersResponse_members[2] = {
+{
+ UA_TYPENAME("responseHeader") /* .memberName */
+ UA_TYPES_RESPONSEHEADER, /* .memberTypeIndex */
+ 0, /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("servers") /* .memberName */
+ UA_TYPES_APPLICATIONDESCRIPTION, /* .memberTypeIndex */
+ offsetof(UA_FindServersResponse, serversSize) - offsetof(UA_FindServersResponse, responseHeader) - sizeof(UA_ResponseHeader), /* .padding */
+ true, /* .namespaceZero */
+ true /* .isArray */
+}};
+
+/* BrowseNextResponse */
+static UA_DataTypeMember BrowseNextResponse_members[3] = {
+{
+ UA_TYPENAME("responseHeader") /* .memberName */
+ UA_TYPES_RESPONSEHEADER, /* .memberTypeIndex */
+ 0, /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("results") /* .memberName */
+ UA_TYPES_BROWSERESULT, /* .memberTypeIndex */
+ offsetof(UA_BrowseNextResponse, resultsSize) - offsetof(UA_BrowseNextResponse, responseHeader) - sizeof(UA_ResponseHeader), /* .padding */
+ true, /* .namespaceZero */
+ true /* .isArray */
+},
+{
+ UA_TYPENAME("diagnosticInfos") /* .memberName */
+ UA_TYPES_DIAGNOSTICINFO, /* .memberTypeIndex */
+ offsetof(UA_BrowseNextResponse, diagnosticInfosSize) - offsetof(UA_BrowseNextResponse, results) - sizeof(void*), /* .padding */
+ true, /* .namespaceZero */
+ true /* .isArray */
+}};
+
+/* BrowseResponse */
+static UA_DataTypeMember BrowseResponse_members[3] = {
+{
+ UA_TYPENAME("responseHeader") /* .memberName */
+ UA_TYPES_RESPONSEHEADER, /* .memberTypeIndex */
+ 0, /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("results") /* .memberName */
+ UA_TYPES_BROWSERESULT, /* .memberTypeIndex */
+ offsetof(UA_BrowseResponse, resultsSize) - offsetof(UA_BrowseResponse, responseHeader) - sizeof(UA_ResponseHeader), /* .padding */
+ true, /* .namespaceZero */
+ true /* .isArray */
+},
+{
+ UA_TYPENAME("diagnosticInfos") /* .memberName */
+ UA_TYPES_DIAGNOSTICINFO, /* .memberTypeIndex */
+ offsetof(UA_BrowseResponse, diagnosticInfosSize) - offsetof(UA_BrowseResponse, results) - sizeof(void*), /* .padding */
+ true, /* .namespaceZero */
+ true /* .isArray */
+}};
+
+/* CreateSessionResponse */
+static UA_DataTypeMember CreateSessionResponse_members[10] = {
+{
+ UA_TYPENAME("responseHeader") /* .memberName */
+ UA_TYPES_RESPONSEHEADER, /* .memberTypeIndex */
+ 0, /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("sessionId") /* .memberName */
+ UA_TYPES_NODEID, /* .memberTypeIndex */
+ offsetof(UA_CreateSessionResponse, sessionId) - offsetof(UA_CreateSessionResponse, responseHeader) - sizeof(UA_ResponseHeader), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("authenticationToken") /* .memberName */
+ UA_TYPES_NODEID, /* .memberTypeIndex */
+ offsetof(UA_CreateSessionResponse, authenticationToken) - offsetof(UA_CreateSessionResponse, sessionId) - sizeof(UA_NodeId), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("revisedSessionTimeout") /* .memberName */
+ UA_TYPES_DOUBLE, /* .memberTypeIndex */
+ offsetof(UA_CreateSessionResponse, revisedSessionTimeout) - offsetof(UA_CreateSessionResponse, authenticationToken) - sizeof(UA_NodeId), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("serverNonce") /* .memberName */
+ UA_TYPES_BYTESTRING, /* .memberTypeIndex */
+ offsetof(UA_CreateSessionResponse, serverNonce) - offsetof(UA_CreateSessionResponse, revisedSessionTimeout) - sizeof(UA_Double), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("serverCertificate") /* .memberName */
+ UA_TYPES_BYTESTRING, /* .memberTypeIndex */
+ offsetof(UA_CreateSessionResponse, serverCertificate) - offsetof(UA_CreateSessionResponse, serverNonce) - sizeof(UA_ByteString), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("serverEndpoints") /* .memberName */
+ UA_TYPES_ENDPOINTDESCRIPTION, /* .memberTypeIndex */
+ offsetof(UA_CreateSessionResponse, serverEndpointsSize) - offsetof(UA_CreateSessionResponse, serverCertificate) - sizeof(UA_ByteString), /* .padding */
+ true, /* .namespaceZero */
+ true /* .isArray */
+},
+{
+ UA_TYPENAME("serverSoftwareCertificates") /* .memberName */
+ UA_TYPES_SIGNEDSOFTWARECERTIFICATE, /* .memberTypeIndex */
+ offsetof(UA_CreateSessionResponse, serverSoftwareCertificatesSize) - offsetof(UA_CreateSessionResponse, serverEndpoints) - sizeof(void*), /* .padding */
+ true, /* .namespaceZero */
+ true /* .isArray */
+},
+{
+ UA_TYPENAME("serverSignature") /* .memberName */
+ UA_TYPES_SIGNATUREDATA, /* .memberTypeIndex */
+ offsetof(UA_CreateSessionResponse, serverSignature) - offsetof(UA_CreateSessionResponse, serverSoftwareCertificates) - sizeof(void*), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("maxRequestMessageSize") /* .memberName */
+ UA_TYPES_UINT32, /* .memberTypeIndex */
+ offsetof(UA_CreateSessionResponse, maxRequestMessageSize) - offsetof(UA_CreateSessionResponse, serverSignature) - sizeof(UA_SignatureData), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+}};
+
+/* QueryFirstRequest */
+static UA_DataTypeMember QueryFirstRequest_members[6] = {
+{
+ UA_TYPENAME("requestHeader") /* .memberName */
+ UA_TYPES_REQUESTHEADER, /* .memberTypeIndex */
+ 0, /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("view") /* .memberName */
+ UA_TYPES_VIEWDESCRIPTION, /* .memberTypeIndex */
+ offsetof(UA_QueryFirstRequest, view) - offsetof(UA_QueryFirstRequest, requestHeader) - sizeof(UA_RequestHeader), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("nodeTypes") /* .memberName */
+ UA_TYPES_NODETYPEDESCRIPTION, /* .memberTypeIndex */
+ offsetof(UA_QueryFirstRequest, nodeTypesSize) - offsetof(UA_QueryFirstRequest, view) - sizeof(UA_ViewDescription), /* .padding */
+ true, /* .namespaceZero */
+ true /* .isArray */
+},
+{
+ UA_TYPENAME("filter") /* .memberName */
+ UA_TYPES_CONTENTFILTER, /* .memberTypeIndex */
+ offsetof(UA_QueryFirstRequest, filter) - offsetof(UA_QueryFirstRequest, nodeTypes) - sizeof(void*), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("maxDataSetsToReturn") /* .memberName */
+ UA_TYPES_UINT32, /* .memberTypeIndex */
+ offsetof(UA_QueryFirstRequest, maxDataSetsToReturn) - offsetof(UA_QueryFirstRequest, filter) - sizeof(UA_ContentFilter), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("maxReferencesToReturn") /* .memberName */
+ UA_TYPES_UINT32, /* .memberTypeIndex */
+ offsetof(UA_QueryFirstRequest, maxReferencesToReturn) - offsetof(UA_QueryFirstRequest, maxDataSetsToReturn) - sizeof(UA_UInt32), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+}};
+const UA_DataType UA_TYPES[UA_TYPES_COUNT] = {
+/* Boolean */
+{
+ UA_TYPENAME("Boolean") /* .typeName */
+ {0, UA_NODEIDTYPE_NUMERIC, {1}}, /* .typeId */
+ sizeof(UA_Boolean), /* .memSize */
+ UA_TYPES_BOOLEAN, /* .typeIndex */
+ 1, /* .membersSize */
+ true, /* .builtin */
+ true, /* .pointerFree */
+ true, /* .overlayable */
+ 0, /* .binaryEncodingId */
+ Boolean_members /* .members */
+},
+/* SByte */
+{
+ UA_TYPENAME("SByte") /* .typeName */
+ {0, UA_NODEIDTYPE_NUMERIC, {2}}, /* .typeId */
+ sizeof(UA_SByte), /* .memSize */
+ UA_TYPES_SBYTE, /* .typeIndex */
+ 1, /* .membersSize */
+ true, /* .builtin */
+ true, /* .pointerFree */
+ true, /* .overlayable */
+ 0, /* .binaryEncodingId */
+ SByte_members /* .members */
+},
+/* Byte */
+{
+ UA_TYPENAME("Byte") /* .typeName */
+ {0, UA_NODEIDTYPE_NUMERIC, {3}}, /* .typeId */
+ sizeof(UA_Byte), /* .memSize */
+ UA_TYPES_BYTE, /* .typeIndex */
+ 1, /* .membersSize */
+ true, /* .builtin */
+ true, /* .pointerFree */
+ true, /* .overlayable */
+ 0, /* .binaryEncodingId */
+ Byte_members /* .members */
+},
+/* Int16 */
+{
+ UA_TYPENAME("Int16") /* .typeName */
+ {0, UA_NODEIDTYPE_NUMERIC, {4}}, /* .typeId */
+ sizeof(UA_Int16), /* .memSize */
+ UA_TYPES_INT16, /* .typeIndex */
+ 1, /* .membersSize */
+ true, /* .builtin */
+ true, /* .pointerFree */
+ UA_BINARY_OVERLAYABLE_INTEGER, /* .overlayable */
+ 0, /* .binaryEncodingId */
+ Int16_members /* .members */
+},
+/* UInt16 */
+{
+ UA_TYPENAME("UInt16") /* .typeName */
+ {0, UA_NODEIDTYPE_NUMERIC, {5}}, /* .typeId */
+ sizeof(UA_UInt16), /* .memSize */
+ UA_TYPES_UINT16, /* .typeIndex */
+ 1, /* .membersSize */
+ true, /* .builtin */
+ true, /* .pointerFree */
+ UA_BINARY_OVERLAYABLE_INTEGER, /* .overlayable */
+ 0, /* .binaryEncodingId */
+ UInt16_members /* .members */
+},
+/* Int32 */
+{
+ UA_TYPENAME("Int32") /* .typeName */
+ {0, UA_NODEIDTYPE_NUMERIC, {6}}, /* .typeId */
+ sizeof(UA_Int32), /* .memSize */
+ UA_TYPES_INT32, /* .typeIndex */
+ 1, /* .membersSize */
+ true, /* .builtin */
+ true, /* .pointerFree */
+ UA_BINARY_OVERLAYABLE_INTEGER, /* .overlayable */
+ 0, /* .binaryEncodingId */
+ Int32_members /* .members */
+},
+/* UInt32 */
+{
+ UA_TYPENAME("UInt32") /* .typeName */
+ {0, UA_NODEIDTYPE_NUMERIC, {7}}, /* .typeId */
+ sizeof(UA_UInt32), /* .memSize */
+ UA_TYPES_UINT32, /* .typeIndex */
+ 1, /* .membersSize */
+ true, /* .builtin */
+ true, /* .pointerFree */
+ UA_BINARY_OVERLAYABLE_INTEGER, /* .overlayable */
+ 0, /* .binaryEncodingId */
+ UInt32_members /* .members */
+},
+/* Int64 */
+{
+ UA_TYPENAME("Int64") /* .typeName */
+ {0, UA_NODEIDTYPE_NUMERIC, {8}}, /* .typeId */
+ sizeof(UA_Int64), /* .memSize */
+ UA_TYPES_INT64, /* .typeIndex */
+ 1, /* .membersSize */
+ true, /* .builtin */
+ true, /* .pointerFree */
+ UA_BINARY_OVERLAYABLE_INTEGER, /* .overlayable */
+ 0, /* .binaryEncodingId */
+ Int64_members /* .members */
+},
+/* UInt64 */
+{
+ UA_TYPENAME("UInt64") /* .typeName */
+ {0, UA_NODEIDTYPE_NUMERIC, {9}}, /* .typeId */
+ sizeof(UA_UInt64), /* .memSize */
+ UA_TYPES_UINT64, /* .typeIndex */
+ 1, /* .membersSize */
+ true, /* .builtin */
+ true, /* .pointerFree */
+ UA_BINARY_OVERLAYABLE_INTEGER, /* .overlayable */
+ 0, /* .binaryEncodingId */
+ UInt64_members /* .members */
+},
+/* Float */
+{
+ UA_TYPENAME("Float") /* .typeName */
+ {0, UA_NODEIDTYPE_NUMERIC, {10}}, /* .typeId */
+ sizeof(UA_Float), /* .memSize */
+ UA_TYPES_FLOAT, /* .typeIndex */
+ 1, /* .membersSize */
+ true, /* .builtin */
+ true, /* .pointerFree */
+ UA_BINARY_OVERLAYABLE_FLOAT, /* .overlayable */
+ 0, /* .binaryEncodingId */
+ Float_members /* .members */
+},
+/* Double */
+{
+ UA_TYPENAME("Double") /* .typeName */
+ {0, UA_NODEIDTYPE_NUMERIC, {11}}, /* .typeId */
+ sizeof(UA_Double), /* .memSize */
+ UA_TYPES_DOUBLE, /* .typeIndex */
+ 1, /* .membersSize */
+ true, /* .builtin */
+ true, /* .pointerFree */
+ UA_BINARY_OVERLAYABLE_FLOAT, /* .overlayable */
+ 0, /* .binaryEncodingId */
+ Double_members /* .members */
+},
+/* String */
+{
+ UA_TYPENAME("String") /* .typeName */
+ {0, UA_NODEIDTYPE_NUMERIC, {12}}, /* .typeId */
+ sizeof(UA_String), /* .memSize */
+ UA_TYPES_STRING, /* .typeIndex */
+ 1, /* .membersSize */
+ true, /* .builtin */
+ false, /* .pointerFree */
+ false, /* .overlayable */
+ 0, /* .binaryEncodingId */
+ String_members /* .members */
+},
+/* DateTime */
+{
+ UA_TYPENAME("DateTime") /* .typeName */
+ {0, UA_NODEIDTYPE_NUMERIC, {13}}, /* .typeId */
+ sizeof(UA_DateTime), /* .memSize */
+ UA_TYPES_DATETIME, /* .typeIndex */
+ 1, /* .membersSize */
+ true, /* .builtin */
+ true, /* .pointerFree */
+ UA_BINARY_OVERLAYABLE_INTEGER, /* .overlayable */
+ 0, /* .binaryEncodingId */
+ DateTime_members /* .members */
+},
+/* Guid */
+{
+ UA_TYPENAME("Guid") /* .typeName */
+ {0, UA_NODEIDTYPE_NUMERIC, {14}}, /* .typeId */
+ sizeof(UA_Guid), /* .memSize */
+ UA_TYPES_GUID, /* .typeIndex */
+ 1, /* .membersSize */
+ true, /* .builtin */
+ 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, /* .binaryEncodingId */
+ Guid_members /* .members */
+},
+/* ByteString */
+{
+ UA_TYPENAME("ByteString") /* .typeName */
+ {0, UA_NODEIDTYPE_NUMERIC, {15}}, /* .typeId */
+ sizeof(UA_ByteString), /* .memSize */
+ UA_TYPES_BYTESTRING, /* .typeIndex */
+ 1, /* .membersSize */
+ true, /* .builtin */
+ false, /* .pointerFree */
+ false, /* .overlayable */
+ 0, /* .binaryEncodingId */
+ ByteString_members /* .members */
+},
+/* XmlElement */
+{
+ UA_TYPENAME("XmlElement") /* .typeName */
+ {0, UA_NODEIDTYPE_NUMERIC, {16}}, /* .typeId */
+ sizeof(UA_XmlElement), /* .memSize */
+ UA_TYPES_XMLELEMENT, /* .typeIndex */
+ 1, /* .membersSize */
+ true, /* .builtin */
+ false, /* .pointerFree */
+ false, /* .overlayable */
+ 0, /* .binaryEncodingId */
+ XmlElement_members /* .members */
+},
+/* NodeId */
+{
+ UA_TYPENAME("NodeId") /* .typeName */
+ {0, UA_NODEIDTYPE_NUMERIC, {17}}, /* .typeId */
+ sizeof(UA_NodeId), /* .memSize */
+ UA_TYPES_NODEID, /* .typeIndex */
+ 1, /* .membersSize */
+ true, /* .builtin */
+ false, /* .pointerFree */
+ false, /* .overlayable */
+ 0, /* .binaryEncodingId */
+ NodeId_members /* .members */
+},
+/* ExpandedNodeId */
+{
+ UA_TYPENAME("ExpandedNodeId") /* .typeName */
+ {0, UA_NODEIDTYPE_NUMERIC, {18}}, /* .typeId */
+ sizeof(UA_ExpandedNodeId), /* .memSize */
+ UA_TYPES_EXPANDEDNODEID, /* .typeIndex */
+ 1, /* .membersSize */
+ true, /* .builtin */
+ false, /* .pointerFree */
+ false, /* .overlayable */
+ 0, /* .binaryEncodingId */
+ ExpandedNodeId_members /* .members */
+},
+/* StatusCode */
+{
+ UA_TYPENAME("StatusCode") /* .typeName */
+ {0, UA_NODEIDTYPE_NUMERIC, {19}}, /* .typeId */
+ sizeof(UA_StatusCode), /* .memSize */
+ UA_TYPES_STATUSCODE, /* .typeIndex */
+ 1, /* .membersSize */
+ true, /* .builtin */
+ true, /* .pointerFree */
+ UA_BINARY_OVERLAYABLE_INTEGER, /* .overlayable */
+ 0, /* .binaryEncodingId */
+ StatusCode_members /* .members */
+},
+/* QualifiedName */
+{
+ UA_TYPENAME("QualifiedName") /* .typeName */
+ {0, UA_NODEIDTYPE_NUMERIC, {20}}, /* .typeId */
+ sizeof(UA_QualifiedName), /* .memSize */
+ UA_TYPES_QUALIFIEDNAME, /* .typeIndex */
+ 2, /* .membersSize */
+ true, /* .builtin */
+ false, /* .pointerFree */
+ false, /* .overlayable */
+ 0, /* .binaryEncodingId */
+ QualifiedName_members /* .members */
+},
+/* LocalizedText */
+{
+ UA_TYPENAME("LocalizedText") /* .typeName */
+ {0, UA_NODEIDTYPE_NUMERIC, {21}}, /* .typeId */
+ sizeof(UA_LocalizedText), /* .memSize */
+ UA_TYPES_LOCALIZEDTEXT, /* .typeIndex */
+ 1, /* .membersSize */
+ true, /* .builtin */
+ false, /* .pointerFree */
+ false, /* .overlayable */
+ 0, /* .binaryEncodingId */
+ LocalizedText_members /* .members */
+},
+/* ExtensionObject */
+{
+ UA_TYPENAME("ExtensionObject") /* .typeName */
+ {0, UA_NODEIDTYPE_NUMERIC, {22}}, /* .typeId */
+ sizeof(UA_ExtensionObject), /* .memSize */
+ UA_TYPES_EXTENSIONOBJECT, /* .typeIndex */
+ 1, /* .membersSize */
+ true, /* .builtin */
+ false, /* .pointerFree */
+ false, /* .overlayable */
+ 0, /* .binaryEncodingId */
+ ExtensionObject_members /* .members */
+},
+/* DataValue */
+{
+ UA_TYPENAME("DataValue") /* .typeName */
+ {0, UA_NODEIDTYPE_NUMERIC, {23}}, /* .typeId */
+ sizeof(UA_DataValue), /* .memSize */
+ UA_TYPES_DATAVALUE, /* .typeIndex */
+ 1, /* .membersSize */
+ true, /* .builtin */
+ false, /* .pointerFree */
+ false, /* .overlayable */
+ 0, /* .binaryEncodingId */
+ DataValue_members /* .members */
+},
+/* Variant */
+{
+ UA_TYPENAME("Variant") /* .typeName */
+ {0, UA_NODEIDTYPE_NUMERIC, {24}}, /* .typeId */
+ sizeof(UA_Variant), /* .memSize */
+ UA_TYPES_VARIANT, /* .typeIndex */
+ 1, /* .membersSize */
+ true, /* .builtin */
+ false, /* .pointerFree */
+ false, /* .overlayable */
+ 0, /* .binaryEncodingId */
+ Variant_members /* .members */
+},
+/* DiagnosticInfo */
+{
+ UA_TYPENAME("DiagnosticInfo") /* .typeName */
+ {0, UA_NODEIDTYPE_NUMERIC, {25}}, /* .typeId */
+ sizeof(UA_DiagnosticInfo), /* .memSize */
+ UA_TYPES_DIAGNOSTICINFO, /* .typeIndex */
+ 1, /* .membersSize */
+ true, /* .builtin */
+ false, /* .pointerFree */
+ false, /* .overlayable */
+ 0, /* .binaryEncodingId */
+ DiagnosticInfo_members /* .members */
+},
+/* SignedSoftwareCertificate */
+{
+ UA_TYPENAME("SignedSoftwareCertificate") /* .typeName */
+ {0, UA_NODEIDTYPE_NUMERIC, {344}}, /* .typeId */
+ sizeof(UA_SignedSoftwareCertificate), /* .memSize */
+ UA_TYPES_SIGNEDSOFTWARECERTIFICATE, /* .typeIndex */
+ 2, /* .membersSize */
+ false, /* .builtin */
+ false, /* .pointerFree */
+ false, /* .overlayable */
+ 346, /* .binaryEncodingId */
+ SignedSoftwareCertificate_members /* .members */
+},
+/* SemanticChangeStructureDataType */
+{
+ UA_TYPENAME("SemanticChangeStructureDataType") /* .typeName */
+ {0, UA_NODEIDTYPE_NUMERIC, {897}}, /* .typeId */
+ sizeof(UA_SemanticChangeStructureDataType), /* .memSize */
+ UA_TYPES_SEMANTICCHANGESTRUCTUREDATATYPE, /* .typeIndex */
+ 2, /* .membersSize */
+ false, /* .builtin */
+ false, /* .pointerFree */
+ false, /* .overlayable */
+ 899, /* .binaryEncodingId */
+ SemanticChangeStructureDataType_members /* .members */
+},
+/* StatusChangeNotification */
+{
+ UA_TYPENAME("StatusChangeNotification") /* .typeName */
+ {0, UA_NODEIDTYPE_NUMERIC, {818}}, /* .typeId */
+ sizeof(UA_StatusChangeNotification), /* .memSize */
+ UA_TYPES_STATUSCHANGENOTIFICATION, /* .typeIndex */
+ 2, /* .membersSize */
+ false, /* .builtin */
+ false, /* .pointerFree */
+ false, /* .overlayable */
+ 820, /* .binaryEncodingId */
+ StatusChangeNotification_members /* .members */
+},
+/* BrowsePathTarget */
+{
+ UA_TYPENAME("BrowsePathTarget") /* .typeName */
+ {0, UA_NODEIDTYPE_NUMERIC, {546}}, /* .typeId */
+ sizeof(UA_BrowsePathTarget), /* .memSize */
+ UA_TYPES_BROWSEPATHTARGET, /* .typeIndex */
+ 2, /* .membersSize */
+ false, /* .builtin */
+ false, /* .pointerFree */
+ false, /* .overlayable */
+ 548, /* .binaryEncodingId */
+ BrowsePathTarget_members /* .members */
+},
+/* ViewAttributes */
+{
+ UA_TYPENAME("ViewAttributes") /* .typeName */
+ {0, UA_NODEIDTYPE_NUMERIC, {373}}, /* .typeId */
+ sizeof(UA_ViewAttributes), /* .memSize */
+ UA_TYPES_VIEWATTRIBUTES, /* .typeIndex */
+ 7, /* .membersSize */
+ false, /* .builtin */
+ false, /* .pointerFree */
+ false, /* .overlayable */
+ 375, /* .binaryEncodingId */
+ ViewAttributes_members /* .members */
+},
+/* RequestHeader */
+{
+ UA_TYPENAME("RequestHeader") /* .typeName */
+ {0, UA_NODEIDTYPE_NUMERIC, {389}}, /* .typeId */
+ sizeof(UA_RequestHeader), /* .memSize */
+ UA_TYPES_REQUESTHEADER, /* .typeIndex */
+ 7, /* .membersSize */
+ false, /* .builtin */
+ false, /* .pointerFree */
+ false, /* .overlayable */
+ 391, /* .binaryEncodingId */
+ RequestHeader_members /* .members */
+},
+/* MonitoredItemModifyResult */
+{
+ UA_TYPENAME("MonitoredItemModifyResult") /* .typeName */
+ {0, UA_NODEIDTYPE_NUMERIC, {758}}, /* .typeId */
+ sizeof(UA_MonitoredItemModifyResult), /* .memSize */
+ UA_TYPES_MONITOREDITEMMODIFYRESULT, /* .typeIndex */
+ 4, /* .membersSize */
+ false, /* .builtin */
+ false, /* .pointerFree */
+ false, /* .overlayable */
+ 760, /* .binaryEncodingId */
+ MonitoredItemModifyResult_members /* .members */
+},
+/* ElementOperand */
+{
+ UA_TYPENAME("ElementOperand") /* .typeName */
+ {0, UA_NODEIDTYPE_NUMERIC, {592}}, /* .typeId */
+ sizeof(UA_ElementOperand), /* .memSize */
+ UA_TYPES_ELEMENTOPERAND, /* .typeIndex */
+ 1, /* .membersSize */
+ false, /* .builtin */
+ true, /* .pointerFree */
+ true
+ && UA_BINARY_OVERLAYABLE_INTEGER, /* .overlayable */
+ 594, /* .binaryEncodingId */
+ ElementOperand_members /* .members */
+},
+/* CloseSecureChannelRequest */
+{
+ UA_TYPENAME("CloseSecureChannelRequest") /* .typeName */
+ {0, UA_NODEIDTYPE_NUMERIC, {450}}, /* .typeId */
+ sizeof(UA_CloseSecureChannelRequest), /* .memSize */
+ UA_TYPES_CLOSESECURECHANNELREQUEST, /* .typeIndex */
+ 1, /* .membersSize */
+ false, /* .builtin */
+ false, /* .pointerFree */
+ false, /* .overlayable */
+ 452, /* .binaryEncodingId */
+ CloseSecureChannelRequest_members /* .members */
+},
+/* AddNodesResult */
+{
+ UA_TYPENAME("AddNodesResult") /* .typeName */
+ {0, UA_NODEIDTYPE_NUMERIC, {483}}, /* .typeId */
+ sizeof(UA_AddNodesResult), /* .memSize */
+ UA_TYPES_ADDNODESRESULT, /* .typeIndex */
+ 2, /* .membersSize */
+ false, /* .builtin */
+ false, /* .pointerFree */
+ false, /* .overlayable */
+ 485, /* .binaryEncodingId */
+ AddNodesResult_members /* .members */
+},
+/* VariableAttributes */
+{
+ UA_TYPENAME("VariableAttributes") /* .typeName */
+ {0, UA_NODEIDTYPE_NUMERIC, {355}}, /* .typeId */
+ sizeof(UA_VariableAttributes), /* .memSize */
+ UA_TYPES_VARIABLEATTRIBUTES, /* .typeIndex */
+ 13, /* .membersSize */
+ false, /* .builtin */
+ false, /* .pointerFree */
+ false, /* .overlayable */
+ 357, /* .binaryEncodingId */
+ VariableAttributes_members /* .members */
+},
+/* NotificationMessage */
+{
+ UA_TYPENAME("NotificationMessage") /* .typeName */
+ {0, UA_NODEIDTYPE_NUMERIC, {803}}, /* .typeId */
+ sizeof(UA_NotificationMessage), /* .memSize */
+ UA_TYPES_NOTIFICATIONMESSAGE, /* .typeIndex */
+ 3, /* .membersSize */
+ false, /* .builtin */
+ false, /* .pointerFree */
+ false, /* .overlayable */
+ 805, /* .binaryEncodingId */
+ NotificationMessage_members /* .members */
+},
+/* FindServersOnNetworkRequest */
+{
+ UA_TYPENAME("FindServersOnNetworkRequest") /* .typeName */
+ {0, UA_NODEIDTYPE_NUMERIC, {12190}}, /* .typeId */
+ sizeof(UA_FindServersOnNetworkRequest), /* .memSize */
+ UA_TYPES_FINDSERVERSONNETWORKREQUEST, /* .typeIndex */
+ 4, /* .membersSize */
+ false, /* .builtin */
+ false, /* .pointerFree */
+ false, /* .overlayable */
+ 12208, /* .binaryEncodingId */
+ FindServersOnNetworkRequest_members /* .members */
+},
+/* EventFieldList */
+{
+ UA_TYPENAME("EventFieldList") /* .typeName */
+ {0, UA_NODEIDTYPE_NUMERIC, {917}}, /* .typeId */
+ sizeof(UA_EventFieldList), /* .memSize */
+ UA_TYPES_EVENTFIELDLIST, /* .typeIndex */
+ 2, /* .membersSize */
+ false, /* .builtin */
+ false, /* .pointerFree */
+ false, /* .overlayable */
+ 919, /* .binaryEncodingId */
+ EventFieldList_members /* .members */
+},
+/* MonitoringMode */
+{
+ UA_TYPENAME("MonitoringMode") /* .typeName */
+ {0, UA_NODEIDTYPE_NUMERIC, {716}}, /* .typeId */
+ sizeof(UA_MonitoringMode), /* .memSize */
+ UA_TYPES_INT32, /* .typeIndex */
+ 1, /* .membersSize */
+ true, /* .builtin */
+ true, /* .pointerFree */
+ UA_BINARY_OVERLAYABLE_INTEGER, /* .overlayable */
+ 0, /* .binaryEncodingId */
+ MonitoringMode_members /* .members */
+},
+/* MdnsDiscoveryConfiguration */
+{
+ UA_TYPENAME("MdnsDiscoveryConfiguration") /* .typeName */
+ {0, UA_NODEIDTYPE_NUMERIC, {12891}}, /* .typeId */
+ sizeof(UA_MdnsDiscoveryConfiguration), /* .memSize */
+ UA_TYPES_MDNSDISCOVERYCONFIGURATION, /* .typeIndex */
+ 2, /* .membersSize */
+ false, /* .builtin */
+ false, /* .pointerFree */
+ false, /* .overlayable */
+ 12901, /* .binaryEncodingId */
+ MdnsDiscoveryConfiguration_members /* .members */
+},
+/* CallMethodResult */
+{
+ UA_TYPENAME("CallMethodResult") /* .typeName */
+ {0, UA_NODEIDTYPE_NUMERIC, {707}}, /* .typeId */
+ sizeof(UA_CallMethodResult), /* .memSize */
+ UA_TYPES_CALLMETHODRESULT, /* .typeIndex */
+ 4, /* .membersSize */
+ false, /* .builtin */
+ false, /* .pointerFree */
+ false, /* .overlayable */
+ 709, /* .binaryEncodingId */
+ CallMethodResult_members /* .members */
+},
+/* ParsingResult */
+{
+ UA_TYPENAME("ParsingResult") /* .typeName */
+ {0, UA_NODEIDTYPE_NUMERIC, {610}}, /* .typeId */
+ sizeof(UA_ParsingResult), /* .memSize */
+ UA_TYPES_PARSINGRESULT, /* .typeIndex */
+ 3, /* .membersSize */
+ false, /* .builtin */
+ false, /* .pointerFree */
+ false, /* .overlayable */
+ 612, /* .binaryEncodingId */
+ ParsingResult_members /* .members */
+},
+/* RelativePathElement */
+{
+ UA_TYPENAME("RelativePathElement") /* .typeName */
+ {0, UA_NODEIDTYPE_NUMERIC, {537}}, /* .typeId */
+ sizeof(UA_RelativePathElement), /* .memSize */
+ UA_TYPES_RELATIVEPATHELEMENT, /* .typeIndex */
+ 4, /* .membersSize */
+ false, /* .builtin */
+ false, /* .pointerFree */
+ false, /* .overlayable */
+ 539, /* .binaryEncodingId */
+ RelativePathElement_members /* .members */
+},
+/* BrowseDirection */
+{
+ UA_TYPENAME("BrowseDirection") /* .typeName */
+ {0, UA_NODEIDTYPE_NUMERIC, {510}}, /* .typeId */
+ sizeof(UA_BrowseDirection), /* .memSize */
+ UA_TYPES_INT32, /* .typeIndex */
+ 1, /* .membersSize */
+ true, /* .builtin */
+ true, /* .pointerFree */
+ UA_BINARY_OVERLAYABLE_INTEGER, /* .overlayable */
+ 0, /* .binaryEncodingId */
+ BrowseDirection_members /* .members */
+},
+/* CallMethodRequest */
+{
+ UA_TYPENAME("CallMethodRequest") /* .typeName */
+ {0, UA_NODEIDTYPE_NUMERIC, {704}}, /* .typeId */
+ sizeof(UA_CallMethodRequest), /* .memSize */
+ UA_TYPES_CALLMETHODREQUEST, /* .typeIndex */
+ 3, /* .membersSize */
+ false, /* .builtin */
+ false, /* .pointerFree */
+ false, /* .overlayable */
+ 706, /* .binaryEncodingId */
+ CallMethodRequest_members /* .members */
+},
+/* RedundancySupport */
+{
+ UA_TYPENAME("RedundancySupport") /* .typeName */
+ {0, UA_NODEIDTYPE_NUMERIC, {851}}, /* .typeId */
+ sizeof(UA_RedundancySupport), /* .memSize */
+ UA_TYPES_INT32, /* .typeIndex */
+ 1, /* .membersSize */
+ true, /* .builtin */
+ true, /* .pointerFree */
+ UA_BINARY_OVERLAYABLE_INTEGER, /* .overlayable */
+ 0, /* .binaryEncodingId */
+ RedundancySupport_members /* .members */
+},
+/* EventNotificationList */
+{
+ UA_TYPENAME("EventNotificationList") /* .typeName */
+ {0, UA_NODEIDTYPE_NUMERIC, {914}}, /* .typeId */
+ sizeof(UA_EventNotificationList), /* .memSize */
+ UA_TYPES_EVENTNOTIFICATIONLIST, /* .typeIndex */
+ 1, /* .membersSize */
+ false, /* .builtin */
+ false, /* .pointerFree */
+ false, /* .overlayable */
+ 916, /* .binaryEncodingId */
+ EventNotificationList_members /* .members */
+},
+/* UnregisterNodesRequest */
+{
+ UA_TYPENAME("UnregisterNodesRequest") /* .typeName */
+ {0, UA_NODEIDTYPE_NUMERIC, {564}}, /* .typeId */
+ sizeof(UA_UnregisterNodesRequest), /* .memSize */
+ UA_TYPES_UNREGISTERNODESREQUEST, /* .typeIndex */
+ 2, /* .membersSize */
+ false, /* .builtin */
+ false, /* .pointerFree */
+ false, /* .overlayable */
+ 566, /* .binaryEncodingId */
+ UnregisterNodesRequest_members /* .members */
+},
+/* ContentFilterElementResult */
+{
+ UA_TYPENAME("ContentFilterElementResult") /* .typeName */
+ {0, UA_NODEIDTYPE_NUMERIC, {604}}, /* .typeId */
+ sizeof(UA_ContentFilterElementResult), /* .memSize */
+ UA_TYPES_CONTENTFILTERELEMENTRESULT, /* .typeIndex */
+ 3, /* .membersSize */
+ false, /* .builtin */
+ false, /* .pointerFree */
+ false, /* .overlayable */
+ 606, /* .binaryEncodingId */
+ ContentFilterElementResult_members /* .members */
+},
+/* SimpleAttributeOperand */
+{
+ UA_TYPENAME("SimpleAttributeOperand") /* .typeName */
+ {0, UA_NODEIDTYPE_NUMERIC, {601}}, /* .typeId */
+ sizeof(UA_SimpleAttributeOperand), /* .memSize */
+ UA_TYPES_SIMPLEATTRIBUTEOPERAND, /* .typeIndex */
+ 4, /* .membersSize */
+ false, /* .builtin */
+ false, /* .pointerFree */
+ false, /* .overlayable */
+ 603, /* .binaryEncodingId */
+ SimpleAttributeOperand_members /* .members */
+},
+/* LiteralOperand */
+{
+ UA_TYPENAME("LiteralOperand") /* .typeName */
+ {0, UA_NODEIDTYPE_NUMERIC, {595}}, /* .typeId */
+ sizeof(UA_LiteralOperand), /* .memSize */
+ UA_TYPES_LITERALOPERAND, /* .typeIndex */
+ 1, /* .membersSize */
+ false, /* .builtin */
+ false, /* .pointerFree */
+ false, /* .overlayable */
+ 597, /* .binaryEncodingId */
+ LiteralOperand_members /* .members */
+},
+/* QueryDataSet */
+{
+ UA_TYPENAME("QueryDataSet") /* .typeName */
+ {0, UA_NODEIDTYPE_NUMERIC, {577}}, /* .typeId */
+ sizeof(UA_QueryDataSet), /* .memSize */
+ UA_TYPES_QUERYDATASET, /* .typeIndex */
+ 3, /* .membersSize */
+ false, /* .builtin */
+ false, /* .pointerFree */
+ false, /* .overlayable */
+ 579, /* .binaryEncodingId */
+ QueryDataSet_members /* .members */
+},
+/* AnonymousIdentityToken */
+{
+ UA_TYPENAME("AnonymousIdentityToken") /* .typeName */
+ {0, UA_NODEIDTYPE_NUMERIC, {319}}, /* .typeId */
+ sizeof(UA_AnonymousIdentityToken), /* .memSize */
+ UA_TYPES_ANONYMOUSIDENTITYTOKEN, /* .typeIndex */
+ 1, /* .membersSize */
+ false, /* .builtin */
+ false, /* .pointerFree */
+ false, /* .overlayable */
+ 321, /* .binaryEncodingId */
+ AnonymousIdentityToken_members /* .members */
+},
+/* SetPublishingModeRequest */
+{
+ UA_TYPENAME("SetPublishingModeRequest") /* .typeName */
+ {0, UA_NODEIDTYPE_NUMERIC, {797}}, /* .typeId */
+ sizeof(UA_SetPublishingModeRequest), /* .memSize */
+ UA_TYPES_SETPUBLISHINGMODEREQUEST, /* .typeIndex */
+ 3, /* .membersSize */
+ false, /* .builtin */
+ false, /* .pointerFree */
+ false, /* .overlayable */
+ 799, /* .binaryEncodingId */
+ SetPublishingModeRequest_members /* .members */
+},
+/* MonitoredItemCreateResult */
+{
+ UA_TYPENAME("MonitoredItemCreateResult") /* .typeName */
+ {0, UA_NODEIDTYPE_NUMERIC, {746}}, /* .typeId */
+ sizeof(UA_MonitoredItemCreateResult), /* .memSize */
+ UA_TYPES_MONITOREDITEMCREATERESULT, /* .typeIndex */
+ 5, /* .membersSize */
+ false, /* .builtin */
+ false, /* .pointerFree */
+ false, /* .overlayable */
+ 748, /* .binaryEncodingId */
+ MonitoredItemCreateResult_members /* .members */
+},
+/* TimestampsToReturn */
+{
+ UA_TYPENAME("TimestampsToReturn") /* .typeName */
+ {0, UA_NODEIDTYPE_NUMERIC, {625}}, /* .typeId */
+ sizeof(UA_TimestampsToReturn), /* .memSize */
+ UA_TYPES_INT32, /* .typeIndex */
+ 1, /* .membersSize */
+ true, /* .builtin */
+ true, /* .pointerFree */
+ UA_BINARY_OVERLAYABLE_INTEGER, /* .overlayable */
+ 0, /* .binaryEncodingId */
+ TimestampsToReturn_members /* .members */
+},
+/* CallRequest */
+{
+ UA_TYPENAME("CallRequest") /* .typeName */
+ {0, UA_NODEIDTYPE_NUMERIC, {710}}, /* .typeId */
+ sizeof(UA_CallRequest), /* .memSize */
+ UA_TYPES_CALLREQUEST, /* .typeIndex */
+ 2, /* .membersSize */
+ false, /* .builtin */
+ false, /* .pointerFree */
+ false, /* .overlayable */
+ 712, /* .binaryEncodingId */
+ CallRequest_members /* .members */
+},
+/* MethodAttributes */
+{
+ UA_TYPENAME("MethodAttributes") /* .typeName */
+ {0, UA_NODEIDTYPE_NUMERIC, {358}}, /* .typeId */
+ sizeof(UA_MethodAttributes), /* .memSize */
+ UA_TYPES_METHODATTRIBUTES, /* .typeIndex */
+ 7, /* .membersSize */
+ false, /* .builtin */
+ false, /* .pointerFree */
+ false, /* .overlayable */
+ 360, /* .binaryEncodingId */
+ MethodAttributes_members /* .members */
+},
+/* DeleteReferencesItem */
+{
+ UA_TYPENAME("DeleteReferencesItem") /* .typeName */
+ {0, UA_NODEIDTYPE_NUMERIC, {385}}, /* .typeId */
+ sizeof(UA_DeleteReferencesItem), /* .memSize */
+ UA_TYPES_DELETEREFERENCESITEM, /* .typeIndex */
+ 5, /* .membersSize */
+ false, /* .builtin */
+ false, /* .pointerFree */
+ false, /* .overlayable */
+ 387, /* .binaryEncodingId */
+ DeleteReferencesItem_members /* .members */
+},
+/* WriteValue */
+{
+ UA_TYPENAME("WriteValue") /* .typeName */
+ {0, UA_NODEIDTYPE_NUMERIC, {668}}, /* .typeId */
+ sizeof(UA_WriteValue), /* .memSize */
+ UA_TYPES_WRITEVALUE, /* .typeIndex */
+ 4, /* .membersSize */
+ false, /* .builtin */
+ false, /* .pointerFree */
+ false, /* .overlayable */
+ 670, /* .binaryEncodingId */
+ WriteValue_members /* .members */
+},
+/* NodeAttributesMask */
+{
+ UA_TYPENAME("NodeAttributesMask") /* .typeName */
+ {0, UA_NODEIDTYPE_NUMERIC, {348}}, /* .typeId */
+ sizeof(UA_NodeAttributesMask), /* .memSize */
+ UA_TYPES_INT32, /* .typeIndex */
+ 1, /* .membersSize */
+ true, /* .builtin */
+ true, /* .pointerFree */
+ UA_BINARY_OVERLAYABLE_INTEGER, /* .overlayable */
+ 0, /* .binaryEncodingId */
+ NodeAttributesMask_members /* .members */
+},
+/* MessageSecurityMode */
+{
+ UA_TYPENAME("MessageSecurityMode") /* .typeName */
+ {0, UA_NODEIDTYPE_NUMERIC, {302}}, /* .typeId */
+ sizeof(UA_MessageSecurityMode), /* .memSize */
+ UA_TYPES_INT32, /* .typeIndex */
+ 1, /* .membersSize */
+ true, /* .builtin */
+ true, /* .pointerFree */
+ UA_BINARY_OVERLAYABLE_INTEGER, /* .overlayable */
+ 0, /* .binaryEncodingId */
+ MessageSecurityMode_members /* .members */
+},
+/* MonitoringParameters */
+{
+ UA_TYPENAME("MonitoringParameters") /* .typeName */
+ {0, UA_NODEIDTYPE_NUMERIC, {740}}, /* .typeId */
+ sizeof(UA_MonitoringParameters), /* .memSize */
+ UA_TYPES_MONITORINGPARAMETERS, /* .typeIndex */
+ 5, /* .membersSize */
+ false, /* .builtin */
+ false, /* .pointerFree */
+ false, /* .overlayable */
+ 742, /* .binaryEncodingId */
+ MonitoringParameters_members /* .members */
+},
+/* ReferenceNode */
+{
+ UA_TYPENAME("ReferenceNode") /* .typeName */
+ {0, UA_NODEIDTYPE_NUMERIC, {285}}, /* .typeId */
+ sizeof(UA_ReferenceNode), /* .memSize */
+ UA_TYPES_REFERENCENODE, /* .typeIndex */
+ 3, /* .membersSize */
+ false, /* .builtin */
+ false, /* .pointerFree */
+ false, /* .overlayable */
+ 287, /* .binaryEncodingId */
+ ReferenceNode_members /* .members */
+},
+/* Argument */
+{
+ UA_TYPENAME("Argument") /* .typeName */
+ {0, UA_NODEIDTYPE_NUMERIC, {296}}, /* .typeId */
+ sizeof(UA_Argument), /* .memSize */
+ UA_TYPES_ARGUMENT, /* .typeIndex */
+ 5, /* .membersSize */
+ false, /* .builtin */
+ false, /* .pointerFree */
+ false, /* .overlayable */
+ 298, /* .binaryEncodingId */
+ Argument_members /* .members */
+},
+/* ChannelSecurityToken */
+{
+ UA_TYPENAME("ChannelSecurityToken") /* .typeName */
+ {0, UA_NODEIDTYPE_NUMERIC, {441}}, /* .typeId */
+ sizeof(UA_ChannelSecurityToken), /* .memSize */
+ UA_TYPES_CHANNELSECURITYTOKEN, /* .typeIndex */
+ 4, /* .membersSize */
+ false, /* .builtin */
+ true, /* .pointerFree */
+ true
+ && UA_BINARY_OVERLAYABLE_INTEGER
+ && UA_BINARY_OVERLAYABLE_INTEGER
+ && offsetof(UA_ChannelSecurityToken, tokenId) == (offsetof(UA_ChannelSecurityToken, channelId) + sizeof(UA_UInt32))
+ && UA_BINARY_OVERLAYABLE_INTEGER
+ && offsetof(UA_ChannelSecurityToken, createdAt) == (offsetof(UA_ChannelSecurityToken, tokenId) + sizeof(UA_UInt32))
+ && UA_BINARY_OVERLAYABLE_INTEGER
+ && offsetof(UA_ChannelSecurityToken, revisedLifetime) == (offsetof(UA_ChannelSecurityToken, createdAt) + sizeof(UA_DateTime)), /* .overlayable */
+ 443, /* .binaryEncodingId */
+ ChannelSecurityToken_members /* .members */
+},
+/* UserIdentityToken */
+{
+ UA_TYPENAME("UserIdentityToken") /* .typeName */
+ {0, UA_NODEIDTYPE_NUMERIC, {316}}, /* .typeId */
+ sizeof(UA_UserIdentityToken), /* .memSize */
+ UA_TYPES_USERIDENTITYTOKEN, /* .typeIndex */
+ 1, /* .membersSize */
+ false, /* .builtin */
+ false, /* .pointerFree */
+ false, /* .overlayable */
+ 318, /* .binaryEncodingId */
+ UserIdentityToken_members /* .members */
+},
+/* SignatureData */
+{
+ UA_TYPENAME("SignatureData") /* .typeName */
+ {0, UA_NODEIDTYPE_NUMERIC, {456}}, /* .typeId */
+ sizeof(UA_SignatureData), /* .memSize */
+ UA_TYPES_SIGNATUREDATA, /* .typeIndex */
+ 2, /* .membersSize */
+ false, /* .builtin */
+ false, /* .pointerFree */
+ false, /* .overlayable */
+ 458, /* .binaryEncodingId */
+ SignatureData_members /* .members */
+},
+/* ObjectTypeAttributes */
+{
+ UA_TYPENAME("ObjectTypeAttributes") /* .typeName */
+ {0, UA_NODEIDTYPE_NUMERIC, {361}}, /* .typeId */
+ sizeof(UA_ObjectTypeAttributes), /* .memSize */
+ UA_TYPES_OBJECTTYPEATTRIBUTES, /* .typeIndex */
+ 6, /* .membersSize */
+ false, /* .builtin */
+ false, /* .pointerFree */
+ false, /* .overlayable */
+ 363, /* .binaryEncodingId */
+ ObjectTypeAttributes_members /* .members */
+},
+/* DeadbandType */
+{
+ UA_TYPENAME("DeadbandType") /* .typeName */
+ {0, UA_NODEIDTYPE_NUMERIC, {718}}, /* .typeId */
+ sizeof(UA_DeadbandType), /* .memSize */
+ UA_TYPES_INT32, /* .typeIndex */
+ 1, /* .membersSize */
+ true, /* .builtin */
+ true, /* .pointerFree */
+ UA_BINARY_OVERLAYABLE_INTEGER, /* .overlayable */
+ 0, /* .binaryEncodingId */
+ DeadbandType_members /* .members */
+},
+/* SecurityTokenRequestType */
+{
+ UA_TYPENAME("SecurityTokenRequestType") /* .typeName */
+ {0, UA_NODEIDTYPE_NUMERIC, {315}}, /* .typeId */
+ sizeof(UA_SecurityTokenRequestType), /* .memSize */
+ UA_TYPES_INT32, /* .typeIndex */
+ 1, /* .membersSize */
+ true, /* .builtin */
+ true, /* .pointerFree */
+ UA_BINARY_OVERLAYABLE_INTEGER, /* .overlayable */
+ 0, /* .binaryEncodingId */
+ SecurityTokenRequestType_members /* .members */
+},
+/* NodeAttributes */
+{
+ UA_TYPENAME("NodeAttributes") /* .typeName */
+ {0, UA_NODEIDTYPE_NUMERIC, {349}}, /* .typeId */
+ sizeof(UA_NodeAttributes), /* .memSize */
+ UA_TYPES_NODEATTRIBUTES, /* .typeIndex */
+ 5, /* .membersSize */
+ false, /* .builtin */
+ false, /* .pointerFree */
+ false, /* .overlayable */
+ 351, /* .binaryEncodingId */
+ NodeAttributes_members /* .members */
+},
+/* DataChangeTrigger */
+{
+ UA_TYPENAME("DataChangeTrigger") /* .typeName */
+ {0, UA_NODEIDTYPE_NUMERIC, {717}}, /* .typeId */
+ sizeof(UA_DataChangeTrigger), /* .memSize */
+ UA_TYPES_INT32, /* .typeIndex */
+ 1, /* .membersSize */
+ true, /* .builtin */
+ true, /* .pointerFree */
+ UA_BINARY_OVERLAYABLE_INTEGER, /* .overlayable */
+ 0, /* .binaryEncodingId */
+ DataChangeTrigger_members /* .members */
+},
+/* BuildInfo */
+{
+ UA_TYPENAME("BuildInfo") /* .typeName */
+ {0, UA_NODEIDTYPE_NUMERIC, {338}}, /* .typeId */
+ sizeof(UA_BuildInfo), /* .memSize */
+ UA_TYPES_BUILDINFO, /* .typeIndex */
+ 6, /* .membersSize */
+ false, /* .builtin */
+ false, /* .pointerFree */
+ false, /* .overlayable */
+ 340, /* .binaryEncodingId */
+ BuildInfo_members /* .members */
+},
+/* NodeClass */
+{
+ UA_TYPENAME("NodeClass") /* .typeName */
+ {0, UA_NODEIDTYPE_NUMERIC, {257}}, /* .typeId */
+ sizeof(UA_NodeClass), /* .memSize */
+ UA_TYPES_INT32, /* .typeIndex */
+ 1, /* .membersSize */
+ true, /* .builtin */
+ true, /* .pointerFree */
+ UA_BINARY_OVERLAYABLE_INTEGER, /* .overlayable */
+ 0, /* .binaryEncodingId */
+ NodeClass_members /* .members */
+},
+/* SubscriptionDiagnosticsDataType */
+{
+ UA_TYPENAME("SubscriptionDiagnosticsDataType") /* .typeName */
+ {0, UA_NODEIDTYPE_NUMERIC, {874}}, /* .typeId */
+ sizeof(UA_SubscriptionDiagnosticsDataType), /* .memSize */
+ UA_TYPES_SUBSCRIPTIONDIAGNOSTICSDATATYPE, /* .typeIndex */
+ 31, /* .membersSize */
+ false, /* .builtin */
+ false, /* .pointerFree */
+ false, /* .overlayable */
+ 876, /* .binaryEncodingId */
+ SubscriptionDiagnosticsDataType_members /* .members */
+},
+/* FilterOperand */
+{
+ UA_TYPENAME("FilterOperand") /* .typeName */
+ {0, UA_NODEIDTYPE_NUMERIC, {589}}, /* .typeId */
+ sizeof(UA_FilterOperand), /* .memSize */
+ UA_TYPES_FILTEROPERAND, /* .typeIndex */
+ 0, /* .membersSize */
+ false, /* .builtin */
+ true, /* .pointerFree */
+ true, /* .overlayable */
+ 591, /* .binaryEncodingId */
+ FilterOperand_members /* .members */
+},
+/* MonitoredItemNotification */
+{
+ UA_TYPENAME("MonitoredItemNotification") /* .typeName */
+ {0, UA_NODEIDTYPE_NUMERIC, {806}}, /* .typeId */
+ sizeof(UA_MonitoredItemNotification), /* .memSize */
+ UA_TYPES_MONITOREDITEMNOTIFICATION, /* .typeIndex */
+ 2, /* .membersSize */
+ false, /* .builtin */
+ false, /* .pointerFree */
+ false, /* .overlayable */
+ 808, /* .binaryEncodingId */
+ MonitoredItemNotification_members /* .members */
+},
+/* DeleteNodesItem */
+{
+ UA_TYPENAME("DeleteNodesItem") /* .typeName */
+ {0, UA_NODEIDTYPE_NUMERIC, {382}}, /* .typeId */
+ sizeof(UA_DeleteNodesItem), /* .memSize */
+ UA_TYPES_DELETENODESITEM, /* .typeIndex */
+ 2, /* .membersSize */
+ false, /* .builtin */
+ false, /* .pointerFree */
+ false, /* .overlayable */
+ 384, /* .binaryEncodingId */
+ DeleteNodesItem_members /* .members */
+},
+/* DeleteSubscriptionsRequest */
+{
+ UA_TYPENAME("DeleteSubscriptionsRequest") /* .typeName */
+ {0, UA_NODEIDTYPE_NUMERIC, {845}}, /* .typeId */
+ sizeof(UA_DeleteSubscriptionsRequest), /* .memSize */
+ UA_TYPES_DELETESUBSCRIPTIONSREQUEST, /* .typeIndex */
+ 2, /* .membersSize */
+ false, /* .builtin */
+ false, /* .pointerFree */
+ false, /* .overlayable */
+ 847, /* .binaryEncodingId */
+ DeleteSubscriptionsRequest_members /* .members */
+},
+/* SubscriptionAcknowledgement */
+{
+ UA_TYPENAME("SubscriptionAcknowledgement") /* .typeName */
+ {0, UA_NODEIDTYPE_NUMERIC, {821}}, /* .typeId */
+ sizeof(UA_SubscriptionAcknowledgement), /* .memSize */
+ UA_TYPES_SUBSCRIPTIONACKNOWLEDGEMENT, /* .typeIndex */
+ 2, /* .membersSize */
+ false, /* .builtin */
+ true, /* .pointerFree */
+ true
+ && UA_BINARY_OVERLAYABLE_INTEGER
+ && UA_BINARY_OVERLAYABLE_INTEGER
+ && offsetof(UA_SubscriptionAcknowledgement, sequenceNumber) == (offsetof(UA_SubscriptionAcknowledgement, subscriptionId) + sizeof(UA_UInt32)), /* .overlayable */
+ 823, /* .binaryEncodingId */
+ SubscriptionAcknowledgement_members /* .members */
+},
+/* ReadValueId */
+{
+ UA_TYPENAME("ReadValueId") /* .typeName */
+ {0, UA_NODEIDTYPE_NUMERIC, {626}}, /* .typeId */
+ sizeof(UA_ReadValueId), /* .memSize */
+ UA_TYPES_READVALUEID, /* .typeIndex */
+ 4, /* .membersSize */
+ false, /* .builtin */
+ false, /* .pointerFree */
+ false, /* .overlayable */
+ 628, /* .binaryEncodingId */
+ ReadValueId_members /* .members */
+},
+/* DataTypeAttributes */
+{
+ UA_TYPENAME("DataTypeAttributes") /* .typeName */
+ {0, UA_NODEIDTYPE_NUMERIC, {370}}, /* .typeId */
+ sizeof(UA_DataTypeAttributes), /* .memSize */
+ UA_TYPES_DATATYPEATTRIBUTES, /* .typeIndex */
+ 6, /* .membersSize */
+ false, /* .builtin */
+ false, /* .pointerFree */
+ false, /* .overlayable */
+ 372, /* .binaryEncodingId */
+ DataTypeAttributes_members /* .members */
+},
+/* ResponseHeader */
+{
+ UA_TYPENAME("ResponseHeader") /* .typeName */
+ {0, UA_NODEIDTYPE_NUMERIC, {392}}, /* .typeId */
+ sizeof(UA_ResponseHeader), /* .memSize */
+ UA_TYPES_RESPONSEHEADER, /* .typeIndex */
+ 6, /* .membersSize */
+ false, /* .builtin */
+ false, /* .pointerFree */
+ false, /* .overlayable */
+ 394, /* .binaryEncodingId */
+ ResponseHeader_members /* .members */
+},
+/* DeleteMonitoredItemsRequest */
+{
+ UA_TYPENAME("DeleteMonitoredItemsRequest") /* .typeName */
+ {0, UA_NODEIDTYPE_NUMERIC, {779}}, /* .typeId */
+ sizeof(UA_DeleteMonitoredItemsRequest), /* .memSize */
+ UA_TYPES_DELETEMONITOREDITEMSREQUEST, /* .typeIndex */
+ 3, /* .membersSize */
+ false, /* .builtin */
+ false, /* .pointerFree */
+ false, /* .overlayable */
+ 781, /* .binaryEncodingId */
+ DeleteMonitoredItemsRequest_members /* .members */
+},
+/* ViewDescription */
+{
+ UA_TYPENAME("ViewDescription") /* .typeName */
+ {0, UA_NODEIDTYPE_NUMERIC, {511}}, /* .typeId */
+ sizeof(UA_ViewDescription), /* .memSize */
+ UA_TYPES_VIEWDESCRIPTION, /* .typeIndex */
+ 3, /* .membersSize */
+ false, /* .builtin */
+ false, /* .pointerFree */
+ false, /* .overlayable */
+ 513, /* .binaryEncodingId */
+ ViewDescription_members /* .members */
+},
+/* ServerOnNetwork */
+{
+ UA_TYPENAME("ServerOnNetwork") /* .typeName */
+ {0, UA_NODEIDTYPE_NUMERIC, {12189}}, /* .typeId */
+ sizeof(UA_ServerOnNetwork), /* .memSize */
+ UA_TYPES_SERVERONNETWORK, /* .typeIndex */
+ 4, /* .membersSize */
+ false, /* .builtin */
+ false, /* .pointerFree */
+ false, /* .overlayable */
+ 12207, /* .binaryEncodingId */
+ ServerOnNetwork_members /* .members */
+},
+/* DeleteMonitoredItemsResponse */
+{
+ UA_TYPENAME("DeleteMonitoredItemsResponse") /* .typeName */
+ {0, UA_NODEIDTYPE_NUMERIC, {782}}, /* .typeId */
+ sizeof(UA_DeleteMonitoredItemsResponse), /* .memSize */
+ UA_TYPES_DELETEMONITOREDITEMSRESPONSE, /* .typeIndex */
+ 3, /* .membersSize */
+ false, /* .builtin */
+ false, /* .pointerFree */
+ false, /* .overlayable */
+ 784, /* .binaryEncodingId */
+ DeleteMonitoredItemsResponse_members /* .members */
+},
+/* FindServersOnNetworkResponse */
+{
+ UA_TYPENAME("FindServersOnNetworkResponse") /* .typeName */
+ {0, UA_NODEIDTYPE_NUMERIC, {12191}}, /* .typeId */
+ sizeof(UA_FindServersOnNetworkResponse), /* .memSize */
+ UA_TYPES_FINDSERVERSONNETWORKRESPONSE, /* .typeIndex */
+ 3, /* .membersSize */
+ false, /* .builtin */
+ false, /* .pointerFree */
+ false, /* .overlayable */
+ 12209, /* .binaryEncodingId */
+ FindServersOnNetworkResponse_members /* .members */
+},
+/* RelativePath */
+{
+ UA_TYPENAME("RelativePath") /* .typeName */
+ {0, UA_NODEIDTYPE_NUMERIC, {540}}, /* .typeId */
+ sizeof(UA_RelativePath), /* .memSize */
+ UA_TYPES_RELATIVEPATH, /* .typeIndex */
+ 1, /* .membersSize */
+ false, /* .builtin */
+ false, /* .pointerFree */
+ false, /* .overlayable */
+ 542, /* .binaryEncodingId */
+ RelativePath_members /* .members */
+},
+/* RegisterNodesRequest */
+{
+ UA_TYPENAME("RegisterNodesRequest") /* .typeName */
+ {0, UA_NODEIDTYPE_NUMERIC, {558}}, /* .typeId */
+ sizeof(UA_RegisterNodesRequest), /* .memSize */
+ UA_TYPES_REGISTERNODESREQUEST, /* .typeIndex */
+ 2, /* .membersSize */
+ false, /* .builtin */
+ false, /* .pointerFree */
+ false, /* .overlayable */
+ 560, /* .binaryEncodingId */
+ RegisterNodesRequest_members /* .members */
+},
+/* AggregateConfiguration */
+{
+ UA_TYPENAME("AggregateConfiguration") /* .typeName */
+ {0, UA_NODEIDTYPE_NUMERIC, {948}}, /* .typeId */
+ sizeof(UA_AggregateConfiguration), /* .memSize */
+ UA_TYPES_AGGREGATECONFIGURATION, /* .typeIndex */
+ 5, /* .membersSize */
+ false, /* .builtin */
+ true, /* .pointerFree */
+ true
+ && true
+ && true
+ && offsetof(UA_AggregateConfiguration, treatUncertainAsBad) == (offsetof(UA_AggregateConfiguration, useServerCapabilitiesDefaults) + sizeof(UA_Boolean))
+ && true
+ && offsetof(UA_AggregateConfiguration, percentDataBad) == (offsetof(UA_AggregateConfiguration, treatUncertainAsBad) + sizeof(UA_Boolean))
+ && true
+ && offsetof(UA_AggregateConfiguration, percentDataGood) == (offsetof(UA_AggregateConfiguration, percentDataBad) + sizeof(UA_Byte))
+ && true
+ && offsetof(UA_AggregateConfiguration, useSlopedExtrapolation) == (offsetof(UA_AggregateConfiguration, percentDataGood) + sizeof(UA_Byte)), /* .overlayable */
+ 950, /* .binaryEncodingId */
+ AggregateConfiguration_members /* .members */
+},
+/* DeleteNodesRequest */
+{
+ UA_TYPENAME("DeleteNodesRequest") /* .typeName */
+ {0, UA_NODEIDTYPE_NUMERIC, {498}}, /* .typeId */
+ sizeof(UA_DeleteNodesRequest), /* .memSize */
+ UA_TYPES_DELETENODESREQUEST, /* .typeIndex */
+ 2, /* .membersSize */
+ false, /* .builtin */
+ false, /* .pointerFree */
+ false, /* .overlayable */
+ 500, /* .binaryEncodingId */
+ DeleteNodesRequest_members /* .members */
+},
+/* PublishResponse */
+{
+ UA_TYPENAME("PublishResponse") /* .typeName */
+ {0, UA_NODEIDTYPE_NUMERIC, {827}}, /* .typeId */
+ sizeof(UA_PublishResponse), /* .memSize */
+ UA_TYPES_PUBLISHRESPONSE, /* .typeIndex */
+ 7, /* .membersSize */
+ false, /* .builtin */
+ false, /* .pointerFree */
+ false, /* .overlayable */
+ 829, /* .binaryEncodingId */
+ PublishResponse_members /* .members */
+},
+/* MonitoredItemModifyRequest */
+{
+ UA_TYPENAME("MonitoredItemModifyRequest") /* .typeName */
+ {0, UA_NODEIDTYPE_NUMERIC, {755}}, /* .typeId */
+ sizeof(UA_MonitoredItemModifyRequest), /* .memSize */
+ UA_TYPES_MONITOREDITEMMODIFYREQUEST, /* .typeIndex */
+ 2, /* .membersSize */
+ false, /* .builtin */
+ false, /* .pointerFree */
+ false, /* .overlayable */
+ 757, /* .binaryEncodingId */
+ MonitoredItemModifyRequest_members /* .members */
+},
+/* ServiceCounterDataType */
+{
+ UA_TYPENAME("ServiceCounterDataType") /* .typeName */
+ {0, UA_NODEIDTYPE_NUMERIC, {871}}, /* .typeId */
+ sizeof(UA_ServiceCounterDataType), /* .memSize */
+ UA_TYPES_SERVICECOUNTERDATATYPE, /* .typeIndex */
+ 2, /* .membersSize */
+ false, /* .builtin */
+ true, /* .pointerFree */
+ true
+ && UA_BINARY_OVERLAYABLE_INTEGER
+ && UA_BINARY_OVERLAYABLE_INTEGER
+ && offsetof(UA_ServiceCounterDataType, errorCount) == (offsetof(UA_ServiceCounterDataType, totalCount) + sizeof(UA_UInt32)), /* .overlayable */
+ 873, /* .binaryEncodingId */
+ ServiceCounterDataType_members /* .members */
+},
+/* ModelChangeStructureDataType */
+{
+ UA_TYPENAME("ModelChangeStructureDataType") /* .typeName */
+ {0, UA_NODEIDTYPE_NUMERIC, {877}}, /* .typeId */
+ sizeof(UA_ModelChangeStructureDataType), /* .memSize */
+ UA_TYPES_MODELCHANGESTRUCTUREDATATYPE, /* .typeIndex */
+ 3, /* .membersSize */
+ false, /* .builtin */
+ false, /* .pointerFree */
+ false, /* .overlayable */
+ 879, /* .binaryEncodingId */
+ ModelChangeStructureDataType_members /* .members */
+},
+/* UserNameIdentityToken */
+{
+ UA_TYPENAME("UserNameIdentityToken") /* .typeName */
+ {0, UA_NODEIDTYPE_NUMERIC, {322}}, /* .typeId */
+ sizeof(UA_UserNameIdentityToken), /* .memSize */
+ UA_TYPES_USERNAMEIDENTITYTOKEN, /* .typeIndex */
+ 4, /* .membersSize */
+ false, /* .builtin */
+ false, /* .pointerFree */
+ false, /* .overlayable */
+ 324, /* .binaryEncodingId */
+ UserNameIdentityToken_members /* .members */
+},
+/* IdType */
+{
+ UA_TYPENAME("IdType") /* .typeName */
+ {0, UA_NODEIDTYPE_NUMERIC, {256}}, /* .typeId */
+ sizeof(UA_IdType), /* .memSize */
+ UA_TYPES_INT32, /* .typeIndex */
+ 1, /* .membersSize */
+ true, /* .builtin */
+ true, /* .pointerFree */
+ UA_BINARY_OVERLAYABLE_INTEGER, /* .overlayable */
+ 0, /* .binaryEncodingId */
+ IdType_members /* .members */
+},
+/* UserTokenType */
+{
+ UA_TYPENAME("UserTokenType") /* .typeName */
+ {0, UA_NODEIDTYPE_NUMERIC, {303}}, /* .typeId */
+ sizeof(UA_UserTokenType), /* .memSize */
+ UA_TYPES_INT32, /* .typeIndex */
+ 1, /* .membersSize */
+ true, /* .builtin */
+ true, /* .pointerFree */
+ UA_BINARY_OVERLAYABLE_INTEGER, /* .overlayable */
+ 0, /* .binaryEncodingId */
+ UserTokenType_members /* .members */
+},
+/* SetTriggeringResponse */
+{
+ UA_TYPENAME("SetTriggeringResponse") /* .typeName */
+ {0, UA_NODEIDTYPE_NUMERIC, {776}}, /* .typeId */
+ sizeof(UA_SetTriggeringResponse), /* .memSize */
+ UA_TYPES_SETTRIGGERINGRESPONSE, /* .typeIndex */
+ 5, /* .membersSize */
+ false, /* .builtin */
+ false, /* .pointerFree */
+ false, /* .overlayable */
+ 778, /* .binaryEncodingId */
+ SetTriggeringResponse_members /* .members */
+},
+/* TimeZoneDataType */
+{
+ UA_TYPENAME("TimeZoneDataType") /* .typeName */
+ {0, UA_NODEIDTYPE_NUMERIC, {8912}}, /* .typeId */
+ sizeof(UA_TimeZoneDataType), /* .memSize */
+ UA_TYPES_TIMEZONEDATATYPE, /* .typeIndex */
+ 2, /* .membersSize */
+ false, /* .builtin */
+ true, /* .pointerFree */
+ true
+ && UA_BINARY_OVERLAYABLE_INTEGER
+ && true
+ && offsetof(UA_TimeZoneDataType, daylightSavingInOffset) == (offsetof(UA_TimeZoneDataType, offset) + sizeof(UA_Int16)), /* .overlayable */
+ 8917, /* .binaryEncodingId */
+ TimeZoneDataType_members /* .members */
+},
+/* ActivateSessionRequest */
+{
+ UA_TYPENAME("ActivateSessionRequest") /* .typeName */
+ {0, UA_NODEIDTYPE_NUMERIC, {465}}, /* .typeId */
+ sizeof(UA_ActivateSessionRequest), /* .memSize */
+ UA_TYPES_ACTIVATESESSIONREQUEST, /* .typeIndex */
+ 6, /* .membersSize */
+ false, /* .builtin */
+ false, /* .pointerFree */
+ false, /* .overlayable */
+ 467, /* .binaryEncodingId */
+ ActivateSessionRequest_members /* .members */
+},
+/* OpenSecureChannelResponse */
+{
+ UA_TYPENAME("OpenSecureChannelResponse") /* .typeName */
+ {0, UA_NODEIDTYPE_NUMERIC, {447}}, /* .typeId */
+ sizeof(UA_OpenSecureChannelResponse), /* .memSize */
+ UA_TYPES_OPENSECURECHANNELRESPONSE, /* .typeIndex */
+ 4, /* .membersSize */
+ false, /* .builtin */
+ false, /* .pointerFree */
+ false, /* .overlayable */
+ 449, /* .binaryEncodingId */
+ OpenSecureChannelResponse_members /* .members */
+},
+/* ApplicationType */
+{
+ UA_TYPENAME("ApplicationType") /* .typeName */
+ {0, UA_NODEIDTYPE_NUMERIC, {307}}, /* .typeId */
+ sizeof(UA_ApplicationType), /* .memSize */
+ UA_TYPES_INT32, /* .typeIndex */
+ 1, /* .membersSize */
+ true, /* .builtin */
+ true, /* .pointerFree */
+ UA_BINARY_OVERLAYABLE_INTEGER, /* .overlayable */
+ 0, /* .binaryEncodingId */
+ ApplicationType_members /* .members */
+},
+/* ServerState */
+{
+ UA_TYPENAME("ServerState") /* .typeName */
+ {0, UA_NODEIDTYPE_NUMERIC, {852}}, /* .typeId */
+ sizeof(UA_ServerState), /* .memSize */
+ UA_TYPES_INT32, /* .typeIndex */
+ 1, /* .membersSize */
+ true, /* .builtin */
+ true, /* .pointerFree */
+ UA_BINARY_OVERLAYABLE_INTEGER, /* .overlayable */
+ 0, /* .binaryEncodingId */
+ ServerState_members /* .members */
+},
+/* QueryNextResponse */
+{
+ UA_TYPENAME("QueryNextResponse") /* .typeName */
+ {0, UA_NODEIDTYPE_NUMERIC, {622}}, /* .typeId */
+ sizeof(UA_QueryNextResponse), /* .memSize */
+ UA_TYPES_QUERYNEXTRESPONSE, /* .typeIndex */
+ 3, /* .membersSize */
+ false, /* .builtin */
+ false, /* .pointerFree */
+ false, /* .overlayable */
+ 624, /* .binaryEncodingId */
+ QueryNextResponse_members /* .members */
+},
+/* DiscoveryConfiguration */
+{
+ UA_TYPENAME("DiscoveryConfiguration") /* .typeName */
+ {0, UA_NODEIDTYPE_NUMERIC, {12890}}, /* .typeId */
+ sizeof(UA_DiscoveryConfiguration), /* .memSize */
+ UA_TYPES_DISCOVERYCONFIGURATION, /* .typeIndex */
+ 0, /* .membersSize */
+ false, /* .builtin */
+ true, /* .pointerFree */
+ true, /* .overlayable */
+ 12900, /* .binaryEncodingId */
+ DiscoveryConfiguration_members /* .members */
+},
+/* ActivateSessionResponse */
+{
+ UA_TYPENAME("ActivateSessionResponse") /* .typeName */
+ {0, UA_NODEIDTYPE_NUMERIC, {468}}, /* .typeId */
+ sizeof(UA_ActivateSessionResponse), /* .memSize */
+ UA_TYPES_ACTIVATESESSIONRESPONSE, /* .typeIndex */
+ 4, /* .membersSize */
+ false, /* .builtin */
+ false, /* .pointerFree */
+ false, /* .overlayable */
+ 470, /* .binaryEncodingId */
+ ActivateSessionResponse_members /* .members */
+},
+/* EndpointUrlListDataType */
+{
+ UA_TYPENAME("EndpointUrlListDataType") /* .typeName */
+ {0, UA_NODEIDTYPE_NUMERIC, {11943}}, /* .typeId */
+ sizeof(UA_EndpointUrlListDataType), /* .memSize */
+ UA_TYPES_ENDPOINTURLLISTDATATYPE, /* .typeIndex */
+ 1, /* .membersSize */
+ false, /* .builtin */
+ false, /* .pointerFree */
+ false, /* .overlayable */
+ 11957, /* .binaryEncodingId */
+ EndpointUrlListDataType_members /* .members */
+},
+/* FilterOperator */
+{
+ UA_TYPENAME("FilterOperator") /* .typeName */
+ {0, UA_NODEIDTYPE_NUMERIC, {576}}, /* .typeId */
+ sizeof(UA_FilterOperator), /* .memSize */
+ UA_TYPES_INT32, /* .typeIndex */
+ 1, /* .membersSize */
+ true, /* .builtin */
+ true, /* .pointerFree */
+ UA_BINARY_OVERLAYABLE_INTEGER, /* .overlayable */
+ 0, /* .binaryEncodingId */
+ FilterOperator_members /* .members */
+},
+/* QueryNextRequest */
+{
+ UA_TYPENAME("QueryNextRequest") /* .typeName */
+ {0, UA_NODEIDTYPE_NUMERIC, {619}}, /* .typeId */
+ sizeof(UA_QueryNextRequest), /* .memSize */
+ UA_TYPES_QUERYNEXTREQUEST, /* .typeIndex */
+ 3, /* .membersSize */
+ false, /* .builtin */
+ false, /* .pointerFree */
+ false, /* .overlayable */
+ 621, /* .binaryEncodingId */
+ QueryNextRequest_members /* .members */
+},
+/* WriteResponse */
+{
+ UA_TYPENAME("WriteResponse") /* .typeName */
+ {0, UA_NODEIDTYPE_NUMERIC, {674}}, /* .typeId */
+ sizeof(UA_WriteResponse), /* .memSize */
+ UA_TYPES_WRITERESPONSE, /* .typeIndex */
+ 3, /* .membersSize */
+ false, /* .builtin */
+ false, /* .pointerFree */
+ false, /* .overlayable */
+ 676, /* .binaryEncodingId */
+ WriteResponse_members /* .members */
+},
+/* BrowseNextRequest */
+{
+ UA_TYPENAME("BrowseNextRequest") /* .typeName */
+ {0, UA_NODEIDTYPE_NUMERIC, {531}}, /* .typeId */
+ sizeof(UA_BrowseNextRequest), /* .memSize */
+ UA_TYPES_BROWSENEXTREQUEST, /* .typeIndex */
+ 3, /* .membersSize */
+ false, /* .builtin */
+ false, /* .pointerFree */
+ false, /* .overlayable */
+ 533, /* .binaryEncodingId */
+ BrowseNextRequest_members /* .members */
+},
+/* CreateSubscriptionRequest */
+{
+ UA_TYPENAME("CreateSubscriptionRequest") /* .typeName */
+ {0, UA_NODEIDTYPE_NUMERIC, {785}}, /* .typeId */
+ sizeof(UA_CreateSubscriptionRequest), /* .memSize */
+ UA_TYPES_CREATESUBSCRIPTIONREQUEST, /* .typeIndex */
+ 7, /* .membersSize */
+ false, /* .builtin */
+ false, /* .pointerFree */
+ false, /* .overlayable */
+ 787, /* .binaryEncodingId */
+ CreateSubscriptionRequest_members /* .members */
+},
+/* VariableTypeAttributes */
+{
+ UA_TYPENAME("VariableTypeAttributes") /* .typeName */
+ {0, UA_NODEIDTYPE_NUMERIC, {364}}, /* .typeId */
+ sizeof(UA_VariableTypeAttributes), /* .memSize */
+ UA_TYPES_VARIABLETYPEATTRIBUTES, /* .typeIndex */
+ 10, /* .membersSize */
+ false, /* .builtin */
+ false, /* .pointerFree */
+ false, /* .overlayable */
+ 366, /* .binaryEncodingId */
+ VariableTypeAttributes_members /* .members */
+},
+/* BrowsePathResult */
+{
+ UA_TYPENAME("BrowsePathResult") /* .typeName */
+ {0, UA_NODEIDTYPE_NUMERIC, {549}}, /* .typeId */
+ sizeof(UA_BrowsePathResult), /* .memSize */
+ UA_TYPES_BROWSEPATHRESULT, /* .typeIndex */
+ 2, /* .membersSize */
+ false, /* .builtin */
+ false, /* .pointerFree */
+ false, /* .overlayable */
+ 551, /* .binaryEncodingId */
+ BrowsePathResult_members /* .members */
+},
+/* ModifySubscriptionResponse */
+{
+ UA_TYPENAME("ModifySubscriptionResponse") /* .typeName */
+ {0, UA_NODEIDTYPE_NUMERIC, {794}}, /* .typeId */
+ sizeof(UA_ModifySubscriptionResponse), /* .memSize */
+ UA_TYPES_MODIFYSUBSCRIPTIONRESPONSE, /* .typeIndex */
+ 4, /* .membersSize */
+ false, /* .builtin */
+ false, /* .pointerFree */
+ false, /* .overlayable */
+ 796, /* .binaryEncodingId */
+ ModifySubscriptionResponse_members /* .members */
+},
+/* RedundantServerDataType */
+{
+ UA_TYPENAME("RedundantServerDataType") /* .typeName */
+ {0, UA_NODEIDTYPE_NUMERIC, {853}}, /* .typeId */
+ sizeof(UA_RedundantServerDataType), /* .memSize */
+ UA_TYPES_REDUNDANTSERVERDATATYPE, /* .typeIndex */
+ 3, /* .membersSize */
+ false, /* .builtin */
+ false, /* .pointerFree */
+ false, /* .overlayable */
+ 855, /* .binaryEncodingId */
+ RedundantServerDataType_members /* .members */
+},
+/* RegisterNodesResponse */
+{
+ UA_TYPENAME("RegisterNodesResponse") /* .typeName */
+ {0, UA_NODEIDTYPE_NUMERIC, {561}}, /* .typeId */
+ sizeof(UA_RegisterNodesResponse), /* .memSize */
+ UA_TYPES_REGISTERNODESRESPONSE, /* .typeIndex */
+ 2, /* .membersSize */
+ false, /* .builtin */
+ false, /* .pointerFree */
+ false, /* .overlayable */
+ 563, /* .binaryEncodingId */
+ RegisterNodesResponse_members /* .members */
+},
+/* CloseSessionRequest */
+{
+ UA_TYPENAME("CloseSessionRequest") /* .typeName */
+ {0, UA_NODEIDTYPE_NUMERIC, {471}}, /* .typeId */
+ sizeof(UA_CloseSessionRequest), /* .memSize */
+ UA_TYPES_CLOSESESSIONREQUEST, /* .typeIndex */
+ 2, /* .membersSize */
+ false, /* .builtin */
+ false, /* .pointerFree */
+ false, /* .overlayable */
+ 473, /* .binaryEncodingId */
+ CloseSessionRequest_members /* .members */
+},
+/* ModifyMonitoredItemsResponse */
+{
+ UA_TYPENAME("ModifyMonitoredItemsResponse") /* .typeName */
+ {0, UA_NODEIDTYPE_NUMERIC, {764}}, /* .typeId */
+ sizeof(UA_ModifyMonitoredItemsResponse), /* .memSize */
+ UA_TYPES_MODIFYMONITOREDITEMSRESPONSE, /* .typeIndex */
+ 3, /* .membersSize */
+ false, /* .builtin */
+ false, /* .pointerFree */
+ false, /* .overlayable */
+ 766, /* .binaryEncodingId */
+ ModifyMonitoredItemsResponse_members /* .members */
+},
+/* ModifySubscriptionRequest */
+{
+ UA_TYPENAME("ModifySubscriptionRequest") /* .typeName */
+ {0, UA_NODEIDTYPE_NUMERIC, {791}}, /* .typeId */
+ sizeof(UA_ModifySubscriptionRequest), /* .memSize */
+ UA_TYPES_MODIFYSUBSCRIPTIONREQUEST, /* .typeIndex */
+ 7, /* .membersSize */
+ false, /* .builtin */
+ false, /* .pointerFree */
+ false, /* .overlayable */
+ 793, /* .binaryEncodingId */
+ ModifySubscriptionRequest_members /* .members */
+},
+/* ServerDiagnosticsSummaryDataType */
+{
+ UA_TYPENAME("ServerDiagnosticsSummaryDataType") /* .typeName */
+ {0, UA_NODEIDTYPE_NUMERIC, {859}}, /* .typeId */
+ sizeof(UA_ServerDiagnosticsSummaryDataType), /* .memSize */
+ UA_TYPES_SERVERDIAGNOSTICSSUMMARYDATATYPE, /* .typeIndex */
+ 12, /* .membersSize */
+ false, /* .builtin */
+ true, /* .pointerFree */
+ true
+ && UA_BINARY_OVERLAYABLE_INTEGER
+ && UA_BINARY_OVERLAYABLE_INTEGER
+ && offsetof(UA_ServerDiagnosticsSummaryDataType, currentSessionCount) == (offsetof(UA_ServerDiagnosticsSummaryDataType, serverViewCount) + sizeof(UA_UInt32))
+ && UA_BINARY_OVERLAYABLE_INTEGER
+ && offsetof(UA_ServerDiagnosticsSummaryDataType, cumulatedSessionCount) == (offsetof(UA_ServerDiagnosticsSummaryDataType, currentSessionCount) + sizeof(UA_UInt32))
+ && UA_BINARY_OVERLAYABLE_INTEGER
+ && offsetof(UA_ServerDiagnosticsSummaryDataType, securityRejectedSessionCount) == (offsetof(UA_ServerDiagnosticsSummaryDataType, cumulatedSessionCount) + sizeof(UA_UInt32))
+ && UA_BINARY_OVERLAYABLE_INTEGER
+ && offsetof(UA_ServerDiagnosticsSummaryDataType, rejectedSessionCount) == (offsetof(UA_ServerDiagnosticsSummaryDataType, securityRejectedSessionCount) + sizeof(UA_UInt32))
+ && UA_BINARY_OVERLAYABLE_INTEGER
+ && offsetof(UA_ServerDiagnosticsSummaryDataType, sessionTimeoutCount) == (offsetof(UA_ServerDiagnosticsSummaryDataType, rejectedSessionCount) + sizeof(UA_UInt32))
+ && UA_BINARY_OVERLAYABLE_INTEGER
+ && offsetof(UA_ServerDiagnosticsSummaryDataType, sessionAbortCount) == (offsetof(UA_ServerDiagnosticsSummaryDataType, sessionTimeoutCount) + sizeof(UA_UInt32))
+ && UA_BINARY_OVERLAYABLE_INTEGER
+ && offsetof(UA_ServerDiagnosticsSummaryDataType, currentSubscriptionCount) == (offsetof(UA_ServerDiagnosticsSummaryDataType, sessionAbortCount) + sizeof(UA_UInt32))
+ && UA_BINARY_OVERLAYABLE_INTEGER
+ && offsetof(UA_ServerDiagnosticsSummaryDataType, cumulatedSubscriptionCount) == (offsetof(UA_ServerDiagnosticsSummaryDataType, currentSubscriptionCount) + sizeof(UA_UInt32))
+ && UA_BINARY_OVERLAYABLE_INTEGER
+ && offsetof(UA_ServerDiagnosticsSummaryDataType, publishingIntervalCount) == (offsetof(UA_ServerDiagnosticsSummaryDataType, cumulatedSubscriptionCount) + sizeof(UA_UInt32))
+ && UA_BINARY_OVERLAYABLE_INTEGER
+ && offsetof(UA_ServerDiagnosticsSummaryDataType, securityRejectedRequestsCount) == (offsetof(UA_ServerDiagnosticsSummaryDataType, publishingIntervalCount) + sizeof(UA_UInt32))
+ && UA_BINARY_OVERLAYABLE_INTEGER
+ && offsetof(UA_ServerDiagnosticsSummaryDataType, rejectedRequestsCount) == (offsetof(UA_ServerDiagnosticsSummaryDataType, securityRejectedRequestsCount) + sizeof(UA_UInt32)), /* .overlayable */
+ 861, /* .binaryEncodingId */
+ ServerDiagnosticsSummaryDataType_members /* .members */
+},
+/* UserTokenPolicy */
+{
+ UA_TYPENAME("UserTokenPolicy") /* .typeName */
+ {0, UA_NODEIDTYPE_NUMERIC, {304}}, /* .typeId */
+ sizeof(UA_UserTokenPolicy), /* .memSize */
+ UA_TYPES_USERTOKENPOLICY, /* .typeIndex */
+ 5, /* .membersSize */
+ false, /* .builtin */
+ false, /* .pointerFree */
+ false, /* .overlayable */
+ 306, /* .binaryEncodingId */
+ UserTokenPolicy_members /* .members */
+},
+/* ReferenceTypeAttributes */
+{
+ UA_TYPENAME("ReferenceTypeAttributes") /* .typeName */
+ {0, UA_NODEIDTYPE_NUMERIC, {367}}, /* .typeId */
+ sizeof(UA_ReferenceTypeAttributes), /* .memSize */
+ UA_TYPES_REFERENCETYPEATTRIBUTES, /* .typeIndex */
+ 8, /* .membersSize */
+ false, /* .builtin */
+ false, /* .pointerFree */
+ false, /* .overlayable */
+ 369, /* .binaryEncodingId */
+ ReferenceTypeAttributes_members /* .members */
+},
+/* BrowsePath */
+{
+ UA_TYPENAME("BrowsePath") /* .typeName */
+ {0, UA_NODEIDTYPE_NUMERIC, {543}}, /* .typeId */
+ sizeof(UA_BrowsePath), /* .memSize */
+ UA_TYPES_BROWSEPATH, /* .typeIndex */
+ 2, /* .membersSize */
+ false, /* .builtin */
+ false, /* .pointerFree */
+ false, /* .overlayable */
+ 545, /* .binaryEncodingId */
+ BrowsePath_members /* .members */
+},
+/* SetMonitoringModeRequest */
+{
+ UA_TYPENAME("SetMonitoringModeRequest") /* .typeName */
+ {0, UA_NODEIDTYPE_NUMERIC, {767}}, /* .typeId */
+ sizeof(UA_SetMonitoringModeRequest), /* .memSize */
+ UA_TYPES_SETMONITORINGMODEREQUEST, /* .typeIndex */
+ 4, /* .membersSize */
+ false, /* .builtin */
+ false, /* .pointerFree */
+ false, /* .overlayable */
+ 769, /* .binaryEncodingId */
+ SetMonitoringModeRequest_members /* .members */
+},
+/* UnregisterNodesResponse */
+{
+ UA_TYPENAME("UnregisterNodesResponse") /* .typeName */
+ {0, UA_NODEIDTYPE_NUMERIC, {567}}, /* .typeId */
+ sizeof(UA_UnregisterNodesResponse), /* .memSize */
+ UA_TYPES_UNREGISTERNODESRESPONSE, /* .typeIndex */
+ 1, /* .membersSize */
+ false, /* .builtin */
+ false, /* .pointerFree */
+ false, /* .overlayable */
+ 569, /* .binaryEncodingId */
+ UnregisterNodesResponse_members /* .members */
+},
+/* WriteRequest */
+{
+ UA_TYPENAME("WriteRequest") /* .typeName */
+ {0, UA_NODEIDTYPE_NUMERIC, {671}}, /* .typeId */
+ sizeof(UA_WriteRequest), /* .memSize */
+ UA_TYPES_WRITEREQUEST, /* .typeIndex */
+ 2, /* .membersSize */
+ false, /* .builtin */
+ false, /* .pointerFree */
+ false, /* .overlayable */
+ 673, /* .binaryEncodingId */
+ WriteRequest_members /* .members */
+},
+/* ObjectAttributes */
+{
+ UA_TYPENAME("ObjectAttributes") /* .typeName */
+ {0, UA_NODEIDTYPE_NUMERIC, {352}}, /* .typeId */
+ sizeof(UA_ObjectAttributes), /* .memSize */
+ UA_TYPES_OBJECTATTRIBUTES, /* .typeIndex */
+ 6, /* .membersSize */
+ false, /* .builtin */
+ false, /* .pointerFree */
+ false, /* .overlayable */
+ 354, /* .binaryEncodingId */
+ ObjectAttributes_members /* .members */
+},
+/* BrowseResultMask */
+{
+ UA_TYPENAME("BrowseResultMask") /* .typeName */
+ {0, UA_NODEIDTYPE_NUMERIC, {517}}, /* .typeId */
+ sizeof(UA_BrowseResultMask), /* .memSize */
+ UA_TYPES_INT32, /* .typeIndex */
+ 1, /* .membersSize */
+ true, /* .builtin */
+ true, /* .pointerFree */
+ UA_BINARY_OVERLAYABLE_INTEGER, /* .overlayable */
+ 0, /* .binaryEncodingId */
+ BrowseResultMask_members /* .members */
+},
+/* BrowseDescription */
+{
+ UA_TYPENAME("BrowseDescription") /* .typeName */
+ {0, UA_NODEIDTYPE_NUMERIC, {514}}, /* .typeId */
+ sizeof(UA_BrowseDescription), /* .memSize */
+ UA_TYPES_BROWSEDESCRIPTION, /* .typeIndex */
+ 6, /* .membersSize */
+ false, /* .builtin */
+ false, /* .pointerFree */
+ false, /* .overlayable */
+ 516, /* .binaryEncodingId */
+ BrowseDescription_members /* .members */
+},
+/* SetTriggeringRequest */
+{
+ UA_TYPENAME("SetTriggeringRequest") /* .typeName */
+ {0, UA_NODEIDTYPE_NUMERIC, {773}}, /* .typeId */
+ sizeof(UA_SetTriggeringRequest), /* .memSize */
+ UA_TYPES_SETTRIGGERINGREQUEST, /* .typeIndex */
+ 5, /* .membersSize */
+ false, /* .builtin */
+ false, /* .pointerFree */
+ false, /* .overlayable */
+ 775, /* .binaryEncodingId */
+ SetTriggeringRequest_members /* .members */
+},
+/* SessionSecurityDiagnosticsDataType */
+{
+ UA_TYPENAME("SessionSecurityDiagnosticsDataType") /* .typeName */
+ {0, UA_NODEIDTYPE_NUMERIC, {868}}, /* .typeId */
+ sizeof(UA_SessionSecurityDiagnosticsDataType), /* .memSize */
+ UA_TYPES_SESSIONSECURITYDIAGNOSTICSDATATYPE, /* .typeIndex */
+ 9, /* .membersSize */
+ false, /* .builtin */
+ false, /* .pointerFree */
+ false, /* .overlayable */
+ 870, /* .binaryEncodingId */
+ SessionSecurityDiagnosticsDataType_members /* .members */
+},
+/* RepublishRequest */
+{
+ UA_TYPENAME("RepublishRequest") /* .typeName */
+ {0, UA_NODEIDTYPE_NUMERIC, {830}}, /* .typeId */
+ sizeof(UA_RepublishRequest), /* .memSize */
+ UA_TYPES_REPUBLISHREQUEST, /* .typeIndex */
+ 3, /* .membersSize */
+ false, /* .builtin */
+ false, /* .pointerFree */
+ false, /* .overlayable */
+ 832, /* .binaryEncodingId */
+ RepublishRequest_members /* .members */
+},
+/* GetEndpointsRequest */
+{
+ UA_TYPENAME("GetEndpointsRequest") /* .typeName */
+ {0, UA_NODEIDTYPE_NUMERIC, {426}}, /* .typeId */
+ sizeof(UA_GetEndpointsRequest), /* .memSize */
+ UA_TYPES_GETENDPOINTSREQUEST, /* .typeIndex */
+ 4, /* .membersSize */
+ false, /* .builtin */
+ false, /* .pointerFree */
+ false, /* .overlayable */
+ 428, /* .binaryEncodingId */
+ GetEndpointsRequest_members /* .members */
+},
+/* PublishRequest */
+{
+ UA_TYPENAME("PublishRequest") /* .typeName */
+ {0, UA_NODEIDTYPE_NUMERIC, {824}}, /* .typeId */
+ sizeof(UA_PublishRequest), /* .memSize */
+ UA_TYPES_PUBLISHREQUEST, /* .typeIndex */
+ 2, /* .membersSize */
+ false, /* .builtin */
+ false, /* .pointerFree */
+ false, /* .overlayable */
+ 826, /* .binaryEncodingId */
+ PublishRequest_members /* .members */
+},
+/* DeleteSubscriptionsResponse */
+{
+ UA_TYPENAME("DeleteSubscriptionsResponse") /* .typeName */
+ {0, UA_NODEIDTYPE_NUMERIC, {848}}, /* .typeId */
+ sizeof(UA_DeleteSubscriptionsResponse), /* .memSize */
+ UA_TYPES_DELETESUBSCRIPTIONSRESPONSE, /* .typeIndex */
+ 3, /* .membersSize */
+ false, /* .builtin */
+ false, /* .pointerFree */
+ false, /* .overlayable */
+ 850, /* .binaryEncodingId */
+ DeleteSubscriptionsResponse_members /* .members */
+},
+/* AddNodesResponse */
+{
+ UA_TYPENAME("AddNodesResponse") /* .typeName */
+ {0, UA_NODEIDTYPE_NUMERIC, {489}}, /* .typeId */
+ sizeof(UA_AddNodesResponse), /* .memSize */
+ UA_TYPES_ADDNODESRESPONSE, /* .typeIndex */
+ 3, /* .membersSize */
+ false, /* .builtin */
+ false, /* .pointerFree */
+ false, /* .overlayable */
+ 491, /* .binaryEncodingId */
+ AddNodesResponse_members /* .members */
+},
+/* DataChangeNotification */
+{
+ UA_TYPENAME("DataChangeNotification") /* .typeName */
+ {0, UA_NODEIDTYPE_NUMERIC, {809}}, /* .typeId */
+ sizeof(UA_DataChangeNotification), /* .memSize */
+ UA_TYPES_DATACHANGENOTIFICATION, /* .typeIndex */
+ 2, /* .membersSize */
+ false, /* .builtin */
+ false, /* .pointerFree */
+ false, /* .overlayable */
+ 811, /* .binaryEncodingId */
+ DataChangeNotification_members /* .members */
+},
+/* CloseSecureChannelResponse */
+{
+ UA_TYPENAME("CloseSecureChannelResponse") /* .typeName */
+ {0, UA_NODEIDTYPE_NUMERIC, {453}}, /* .typeId */
+ sizeof(UA_CloseSecureChannelResponse), /* .memSize */
+ UA_TYPES_CLOSESECURECHANNELRESPONSE, /* .typeIndex */
+ 1, /* .membersSize */
+ false, /* .builtin */
+ false, /* .pointerFree */
+ false, /* .overlayable */
+ 455, /* .binaryEncodingId */
+ CloseSecureChannelResponse_members /* .members */
+},
+/* ModifyMonitoredItemsRequest */
+{
+ UA_TYPENAME("ModifyMonitoredItemsRequest") /* .typeName */
+ {0, UA_NODEIDTYPE_NUMERIC, {761}}, /* .typeId */
+ sizeof(UA_ModifyMonitoredItemsRequest), /* .memSize */
+ UA_TYPES_MODIFYMONITOREDITEMSREQUEST, /* .typeIndex */
+ 4, /* .membersSize */
+ false, /* .builtin */
+ false, /* .pointerFree */
+ false, /* .overlayable */
+ 763, /* .binaryEncodingId */
+ ModifyMonitoredItemsRequest_members /* .members */
+},
+/* SetMonitoringModeResponse */
+{
+ UA_TYPENAME("SetMonitoringModeResponse") /* .typeName */
+ {0, UA_NODEIDTYPE_NUMERIC, {770}}, /* .typeId */
+ sizeof(UA_SetMonitoringModeResponse), /* .memSize */
+ UA_TYPES_SETMONITORINGMODERESPONSE, /* .typeIndex */
+ 3, /* .membersSize */
+ false, /* .builtin */
+ false, /* .pointerFree */
+ false, /* .overlayable */
+ 772, /* .binaryEncodingId */
+ SetMonitoringModeResponse_members /* .members */
+},
+/* FindServersRequest */
+{
+ UA_TYPENAME("FindServersRequest") /* .typeName */
+ {0, UA_NODEIDTYPE_NUMERIC, {420}}, /* .typeId */
+ sizeof(UA_FindServersRequest), /* .memSize */
+ UA_TYPES_FINDSERVERSREQUEST, /* .typeIndex */
+ 4, /* .membersSize */
+ false, /* .builtin */
+ false, /* .pointerFree */
+ false, /* .overlayable */
+ 422, /* .binaryEncodingId */
+ FindServersRequest_members /* .members */
+},
+/* ReferenceDescription */
+{
+ UA_TYPENAME("ReferenceDescription") /* .typeName */
+ {0, UA_NODEIDTYPE_NUMERIC, {518}}, /* .typeId */
+ sizeof(UA_ReferenceDescription), /* .memSize */
+ UA_TYPES_REFERENCEDESCRIPTION, /* .typeIndex */
+ 7, /* .membersSize */
+ false, /* .builtin */
+ false, /* .pointerFree */
+ false, /* .overlayable */
+ 520, /* .binaryEncodingId */
+ ReferenceDescription_members /* .members */
+},
+/* SetPublishingModeResponse */
+{
+ UA_TYPENAME("SetPublishingModeResponse") /* .typeName */
+ {0, UA_NODEIDTYPE_NUMERIC, {800}}, /* .typeId */
+ sizeof(UA_SetPublishingModeResponse), /* .memSize */
+ UA_TYPES_SETPUBLISHINGMODERESPONSE, /* .typeIndex */
+ 3, /* .membersSize */
+ false, /* .builtin */
+ false, /* .pointerFree */
+ false, /* .overlayable */
+ 802, /* .binaryEncodingId */
+ SetPublishingModeResponse_members /* .members */
+},
+/* ContentFilterResult */
+{
+ UA_TYPENAME("ContentFilterResult") /* .typeName */
+ {0, UA_NODEIDTYPE_NUMERIC, {607}}, /* .typeId */
+ sizeof(UA_ContentFilterResult), /* .memSize */
+ UA_TYPES_CONTENTFILTERRESULT, /* .typeIndex */
+ 2, /* .membersSize */
+ false, /* .builtin */
+ false, /* .pointerFree */
+ false, /* .overlayable */
+ 609, /* .binaryEncodingId */
+ ContentFilterResult_members /* .members */
+},
+/* RegisterServerResponse */
+{
+ UA_TYPENAME("RegisterServerResponse") /* .typeName */
+ {0, UA_NODEIDTYPE_NUMERIC, {438}}, /* .typeId */
+ sizeof(UA_RegisterServerResponse), /* .memSize */
+ UA_TYPES_REGISTERSERVERRESPONSE, /* .typeIndex */
+ 1, /* .membersSize */
+ false, /* .builtin */
+ false, /* .pointerFree */
+ false, /* .overlayable */
+ 440, /* .binaryEncodingId */
+ RegisterServerResponse_members /* .members */
+},
+/* AddReferencesItem */
+{
+ UA_TYPENAME("AddReferencesItem") /* .typeName */
+ {0, UA_NODEIDTYPE_NUMERIC, {379}}, /* .typeId */
+ sizeof(UA_AddReferencesItem), /* .memSize */
+ UA_TYPES_ADDREFERENCESITEM, /* .typeIndex */
+ 6, /* .membersSize */
+ false, /* .builtin */
+ false, /* .pointerFree */
+ false, /* .overlayable */
+ 381, /* .binaryEncodingId */
+ AddReferencesItem_members /* .members */
+},
+/* QueryDataDescription */
+{
+ UA_TYPENAME("QueryDataDescription") /* .typeName */
+ {0, UA_NODEIDTYPE_NUMERIC, {570}}, /* .typeId */
+ sizeof(UA_QueryDataDescription), /* .memSize */
+ UA_TYPES_QUERYDATADESCRIPTION, /* .typeIndex */
+ 3, /* .membersSize */
+ false, /* .builtin */
+ false, /* .pointerFree */
+ false, /* .overlayable */
+ 572, /* .binaryEncodingId */
+ QueryDataDescription_members /* .members */
+},
+/* CreateSubscriptionResponse */
+{
+ UA_TYPENAME("CreateSubscriptionResponse") /* .typeName */
+ {0, UA_NODEIDTYPE_NUMERIC, {788}}, /* .typeId */
+ sizeof(UA_CreateSubscriptionResponse), /* .memSize */
+ UA_TYPES_CREATESUBSCRIPTIONRESPONSE, /* .typeIndex */
+ 5, /* .membersSize */
+ false, /* .builtin */
+ false, /* .pointerFree */
+ false, /* .overlayable */
+ 790, /* .binaryEncodingId */
+ CreateSubscriptionResponse_members /* .members */
+},
+/* NetworkGroupDataType */
+{
+ UA_TYPENAME("NetworkGroupDataType") /* .typeName */
+ {0, UA_NODEIDTYPE_NUMERIC, {11944}}, /* .typeId */
+ sizeof(UA_NetworkGroupDataType), /* .memSize */
+ UA_TYPES_NETWORKGROUPDATATYPE, /* .typeIndex */
+ 2, /* .membersSize */
+ false, /* .builtin */
+ false, /* .pointerFree */
+ false, /* .overlayable */
+ 11958, /* .binaryEncodingId */
+ NetworkGroupDataType_members /* .members */
+},
+/* DeleteReferencesResponse */
+{
+ UA_TYPENAME("DeleteReferencesResponse") /* .typeName */
+ {0, UA_NODEIDTYPE_NUMERIC, {507}}, /* .typeId */
+ sizeof(UA_DeleteReferencesResponse), /* .memSize */
+ UA_TYPES_DELETEREFERENCESRESPONSE, /* .typeIndex */
+ 3, /* .membersSize */
+ false, /* .builtin */
+ false, /* .pointerFree */
+ false, /* .overlayable */
+ 509, /* .binaryEncodingId */
+ DeleteReferencesResponse_members /* .members */
+},
+/* CreateMonitoredItemsResponse */
+{
+ UA_TYPENAME("CreateMonitoredItemsResponse") /* .typeName */
+ {0, UA_NODEIDTYPE_NUMERIC, {752}}, /* .typeId */
+ sizeof(UA_CreateMonitoredItemsResponse), /* .memSize */
+ UA_TYPES_CREATEMONITOREDITEMSRESPONSE, /* .typeIndex */
+ 3, /* .membersSize */
+ false, /* .builtin */
+ false, /* .pointerFree */
+ false, /* .overlayable */
+ 754, /* .binaryEncodingId */
+ CreateMonitoredItemsResponse_members /* .members */
+},
+/* CallResponse */
+{
+ UA_TYPENAME("CallResponse") /* .typeName */
+ {0, UA_NODEIDTYPE_NUMERIC, {713}}, /* .typeId */
+ sizeof(UA_CallResponse), /* .memSize */
+ UA_TYPES_CALLRESPONSE, /* .typeIndex */
+ 3, /* .membersSize */
+ false, /* .builtin */
+ false, /* .pointerFree */
+ false, /* .overlayable */
+ 715, /* .binaryEncodingId */
+ CallResponse_members /* .members */
+},
+/* DeleteNodesResponse */
+{
+ UA_TYPENAME("DeleteNodesResponse") /* .typeName */
+ {0, UA_NODEIDTYPE_NUMERIC, {501}}, /* .typeId */
+ sizeof(UA_DeleteNodesResponse), /* .memSize */
+ UA_TYPES_DELETENODESRESPONSE, /* .typeIndex */
+ 3, /* .membersSize */
+ false, /* .builtin */
+ false, /* .pointerFree */
+ false, /* .overlayable */
+ 503, /* .binaryEncodingId */
+ DeleteNodesResponse_members /* .members */
+},
+/* RepublishResponse */
+{
+ UA_TYPENAME("RepublishResponse") /* .typeName */
+ {0, UA_NODEIDTYPE_NUMERIC, {833}}, /* .typeId */
+ sizeof(UA_RepublishResponse), /* .memSize */
+ UA_TYPES_REPUBLISHRESPONSE, /* .typeIndex */
+ 2, /* .membersSize */
+ false, /* .builtin */
+ false, /* .pointerFree */
+ false, /* .overlayable */
+ 835, /* .binaryEncodingId */
+ RepublishResponse_members /* .members */
+},
+/* MonitoredItemCreateRequest */
+{
+ UA_TYPENAME("MonitoredItemCreateRequest") /* .typeName */
+ {0, UA_NODEIDTYPE_NUMERIC, {743}}, /* .typeId */
+ sizeof(UA_MonitoredItemCreateRequest), /* .memSize */
+ UA_TYPES_MONITOREDITEMCREATEREQUEST, /* .typeIndex */
+ 3, /* .membersSize */
+ false, /* .builtin */
+ false, /* .pointerFree */
+ false, /* .overlayable */
+ 745, /* .binaryEncodingId */
+ MonitoredItemCreateRequest_members /* .members */
+},
+/* DeleteReferencesRequest */
+{
+ UA_TYPENAME("DeleteReferencesRequest") /* .typeName */
+ {0, UA_NODEIDTYPE_NUMERIC, {504}}, /* .typeId */
+ sizeof(UA_DeleteReferencesRequest), /* .memSize */
+ UA_TYPES_DELETEREFERENCESREQUEST, /* .typeIndex */
+ 2, /* .membersSize */
+ false, /* .builtin */
+ false, /* .pointerFree */
+ false, /* .overlayable */
+ 506, /* .binaryEncodingId */
+ DeleteReferencesRequest_members /* .members */
+},
+/* ReadResponse */
+{
+ UA_TYPENAME("ReadResponse") /* .typeName */
+ {0, UA_NODEIDTYPE_NUMERIC, {632}}, /* .typeId */
+ sizeof(UA_ReadResponse), /* .memSize */
+ UA_TYPES_READRESPONSE, /* .typeIndex */
+ 3, /* .membersSize */
+ false, /* .builtin */
+ false, /* .pointerFree */
+ false, /* .overlayable */
+ 634, /* .binaryEncodingId */
+ ReadResponse_members /* .members */
+},
+/* AddReferencesRequest */
+{
+ UA_TYPENAME("AddReferencesRequest") /* .typeName */
+ {0, UA_NODEIDTYPE_NUMERIC, {492}}, /* .typeId */
+ sizeof(UA_AddReferencesRequest), /* .memSize */
+ UA_TYPES_ADDREFERENCESREQUEST, /* .typeIndex */
+ 2, /* .membersSize */
+ false, /* .builtin */
+ false, /* .pointerFree */
+ false, /* .overlayable */
+ 494, /* .binaryEncodingId */
+ AddReferencesRequest_members /* .members */
+},
+/* ReadRequest */
+{
+ UA_TYPENAME("ReadRequest") /* .typeName */
+ {0, UA_NODEIDTYPE_NUMERIC, {629}}, /* .typeId */
+ sizeof(UA_ReadRequest), /* .memSize */
+ UA_TYPES_READREQUEST, /* .typeIndex */
+ 4, /* .membersSize */
+ false, /* .builtin */
+ false, /* .pointerFree */
+ false, /* .overlayable */
+ 631, /* .binaryEncodingId */
+ ReadRequest_members /* .members */
+},
+/* OpenSecureChannelRequest */
+{
+ UA_TYPENAME("OpenSecureChannelRequest") /* .typeName */
+ {0, UA_NODEIDTYPE_NUMERIC, {444}}, /* .typeId */
+ sizeof(UA_OpenSecureChannelRequest), /* .memSize */
+ UA_TYPES_OPENSECURECHANNELREQUEST, /* .typeIndex */
+ 6, /* .membersSize */
+ false, /* .builtin */
+ false, /* .pointerFree */
+ false, /* .overlayable */
+ 446, /* .binaryEncodingId */
+ OpenSecureChannelRequest_members /* .members */
+},
+/* RegisterServer2Response */
+{
+ UA_TYPENAME("RegisterServer2Response") /* .typeName */
+ {0, UA_NODEIDTYPE_NUMERIC, {12194}}, /* .typeId */
+ sizeof(UA_RegisterServer2Response), /* .memSize */
+ UA_TYPES_REGISTERSERVER2RESPONSE, /* .typeIndex */
+ 3, /* .membersSize */
+ false, /* .builtin */
+ false, /* .pointerFree */
+ false, /* .overlayable */
+ 12212, /* .binaryEncodingId */
+ RegisterServer2Response_members /* .members */
+},
+/* AddNodesItem */
+{
+ UA_TYPENAME("AddNodesItem") /* .typeName */
+ {0, UA_NODEIDTYPE_NUMERIC, {376}}, /* .typeId */
+ sizeof(UA_AddNodesItem), /* .memSize */
+ UA_TYPES_ADDNODESITEM, /* .typeIndex */
+ 7, /* .membersSize */
+ false, /* .builtin */
+ false, /* .pointerFree */
+ false, /* .overlayable */
+ 378, /* .binaryEncodingId */
+ AddNodesItem_members /* .members */
+},
+/* NodeTypeDescription */
+{
+ UA_TYPENAME("NodeTypeDescription") /* .typeName */
+ {0, UA_NODEIDTYPE_NUMERIC, {573}}, /* .typeId */
+ sizeof(UA_NodeTypeDescription), /* .memSize */
+ UA_TYPES_NODETYPEDESCRIPTION, /* .typeIndex */
+ 3, /* .membersSize */
+ false, /* .builtin */
+ false, /* .pointerFree */
+ false, /* .overlayable */
+ 575, /* .binaryEncodingId */
+ NodeTypeDescription_members /* .members */
+},
+/* ServerStatusDataType */
+{
+ UA_TYPENAME("ServerStatusDataType") /* .typeName */
+ {0, UA_NODEIDTYPE_NUMERIC, {862}}, /* .typeId */
+ sizeof(UA_ServerStatusDataType), /* .memSize */
+ UA_TYPES_SERVERSTATUSDATATYPE, /* .typeIndex */
+ 6, /* .membersSize */
+ false, /* .builtin */
+ false, /* .pointerFree */
+ false, /* .overlayable */
+ 864, /* .binaryEncodingId */
+ ServerStatusDataType_members /* .members */
+},
+/* AttributeOperand */
+{
+ UA_TYPENAME("AttributeOperand") /* .typeName */
+ {0, UA_NODEIDTYPE_NUMERIC, {598}}, /* .typeId */
+ sizeof(UA_AttributeOperand), /* .memSize */
+ UA_TYPES_ATTRIBUTEOPERAND, /* .typeIndex */
+ 5, /* .membersSize */
+ false, /* .builtin */
+ false, /* .pointerFree */
+ false, /* .overlayable */
+ 600, /* .binaryEncodingId */
+ AttributeOperand_members /* .members */
+},
+/* AddReferencesResponse */
+{
+ UA_TYPENAME("AddReferencesResponse") /* .typeName */
+ {0, UA_NODEIDTYPE_NUMERIC, {495}}, /* .typeId */
+ sizeof(UA_AddReferencesResponse), /* .memSize */
+ UA_TYPES_ADDREFERENCESRESPONSE, /* .typeIndex */
+ 3, /* .membersSize */
+ false, /* .builtin */
+ false, /* .pointerFree */
+ false, /* .overlayable */
+ 497, /* .binaryEncodingId */
+ AddReferencesResponse_members /* .members */
+},
+/* EventFilterResult */
+{
+ UA_TYPENAME("EventFilterResult") /* .typeName */
+ {0, UA_NODEIDTYPE_NUMERIC, {734}}, /* .typeId */
+ sizeof(UA_EventFilterResult), /* .memSize */
+ UA_TYPES_EVENTFILTERRESULT, /* .typeIndex */
+ 3, /* .membersSize */
+ false, /* .builtin */
+ false, /* .pointerFree */
+ false, /* .overlayable */
+ 736, /* .binaryEncodingId */
+ EventFilterResult_members /* .members */
+},
+/* TranslateBrowsePathsToNodeIdsResponse */
+{
+ UA_TYPENAME("TranslateBrowsePathsToNodeIdsResponse") /* .typeName */
+ {0, UA_NODEIDTYPE_NUMERIC, {555}}, /* .typeId */
+ sizeof(UA_TranslateBrowsePathsToNodeIdsResponse), /* .memSize */
+ UA_TYPES_TRANSLATEBROWSEPATHSTONODEIDSRESPONSE, /* .typeIndex */
+ 3, /* .membersSize */
+ false, /* .builtin */
+ false, /* .pointerFree */
+ false, /* .overlayable */
+ 557, /* .binaryEncodingId */
+ TranslateBrowsePathsToNodeIdsResponse_members /* .members */
+},
+/* DataChangeFilter */
+{
+ UA_TYPENAME("DataChangeFilter") /* .typeName */
+ {0, UA_NODEIDTYPE_NUMERIC, {722}}, /* .typeId */
+ sizeof(UA_DataChangeFilter), /* .memSize */
+ UA_TYPES_DATACHANGEFILTER, /* .typeIndex */
+ 3, /* .membersSize */
+ false, /* .builtin */
+ true, /* .pointerFree */
+ true
+ && UA_BINARY_OVERLAYABLE_INTEGER
+ && UA_BINARY_OVERLAYABLE_INTEGER
+ && offsetof(UA_DataChangeFilter, deadbandType) == (offsetof(UA_DataChangeFilter, trigger) + sizeof(UA_DataChangeTrigger))
+ && UA_BINARY_OVERLAYABLE_FLOAT
+ && offsetof(UA_DataChangeFilter, deadbandValue) == (offsetof(UA_DataChangeFilter, deadbandType) + sizeof(UA_UInt32)), /* .overlayable */
+ 724, /* .binaryEncodingId */
+ DataChangeFilter_members /* .members */
+},
+/* ContentFilterElement */
+{
+ UA_TYPENAME("ContentFilterElement") /* .typeName */
+ {0, UA_NODEIDTYPE_NUMERIC, {583}}, /* .typeId */
+ sizeof(UA_ContentFilterElement), /* .memSize */
+ UA_TYPES_CONTENTFILTERELEMENT, /* .typeIndex */
+ 2, /* .membersSize */
+ false, /* .builtin */
+ false, /* .pointerFree */
+ false, /* .overlayable */
+ 585, /* .binaryEncodingId */
+ ContentFilterElement_members /* .members */
+},
+/* TranslateBrowsePathsToNodeIdsRequest */
+{
+ UA_TYPENAME("TranslateBrowsePathsToNodeIdsRequest") /* .typeName */
+ {0, UA_NODEIDTYPE_NUMERIC, {552}}, /* .typeId */
+ sizeof(UA_TranslateBrowsePathsToNodeIdsRequest), /* .memSize */
+ UA_TYPES_TRANSLATEBROWSEPATHSTONODEIDSREQUEST, /* .typeIndex */
+ 2, /* .membersSize */
+ false, /* .builtin */
+ false, /* .pointerFree */
+ false, /* .overlayable */
+ 554, /* .binaryEncodingId */
+ TranslateBrowsePathsToNodeIdsRequest_members /* .members */
+},
+/* CloseSessionResponse */
+{
+ UA_TYPENAME("CloseSessionResponse") /* .typeName */
+ {0, UA_NODEIDTYPE_NUMERIC, {474}}, /* .typeId */
+ sizeof(UA_CloseSessionResponse), /* .memSize */
+ UA_TYPES_CLOSESESSIONRESPONSE, /* .typeIndex */
+ 1, /* .membersSize */
+ false, /* .builtin */
+ false, /* .pointerFree */
+ false, /* .overlayable */
+ 476, /* .binaryEncodingId */
+ CloseSessionResponse_members /* .members */
+},
+/* ApplicationDescription */
+{
+ UA_TYPENAME("ApplicationDescription") /* .typeName */
+ {0, UA_NODEIDTYPE_NUMERIC, {308}}, /* .typeId */
+ sizeof(UA_ApplicationDescription), /* .memSize */
+ UA_TYPES_APPLICATIONDESCRIPTION, /* .typeIndex */
+ 7, /* .membersSize */
+ false, /* .builtin */
+ false, /* .pointerFree */
+ false, /* .overlayable */
+ 310, /* .binaryEncodingId */
+ ApplicationDescription_members /* .members */
+},
+/* SessionDiagnosticsDataType */
+{
+ UA_TYPENAME("SessionDiagnosticsDataType") /* .typeName */
+ {0, UA_NODEIDTYPE_NUMERIC, {865}}, /* .typeId */
+ sizeof(UA_SessionDiagnosticsDataType), /* .memSize */
+ UA_TYPES_SESSIONDIAGNOSTICSDATATYPE, /* .typeIndex */
+ 43, /* .membersSize */
+ false, /* .builtin */
+ false, /* .pointerFree */
+ false, /* .overlayable */
+ 867, /* .binaryEncodingId */
+ SessionDiagnosticsDataType_members /* .members */
+},
+/* ServiceFault */
+{
+ UA_TYPENAME("ServiceFault") /* .typeName */
+ {0, UA_NODEIDTYPE_NUMERIC, {395}}, /* .typeId */
+ sizeof(UA_ServiceFault), /* .memSize */
+ UA_TYPES_SERVICEFAULT, /* .typeIndex */
+ 1, /* .membersSize */
+ false, /* .builtin */
+ false, /* .pointerFree */
+ false, /* .overlayable */
+ 397, /* .binaryEncodingId */
+ ServiceFault_members /* .members */
+},
+/* RegisteredServer */
+{
+ UA_TYPENAME("RegisteredServer") /* .typeName */
+ {0, UA_NODEIDTYPE_NUMERIC, {432}}, /* .typeId */
+ sizeof(UA_RegisteredServer), /* .memSize */
+ UA_TYPES_REGISTEREDSERVER, /* .typeIndex */
+ 8, /* .membersSize */
+ false, /* .builtin */
+ false, /* .pointerFree */
+ false, /* .overlayable */
+ 434, /* .binaryEncodingId */
+ RegisteredServer_members /* .members */
+},
+/* AggregateFilter */
+{
+ UA_TYPENAME("AggregateFilter") /* .typeName */
+ {0, UA_NODEIDTYPE_NUMERIC, {728}}, /* .typeId */
+ sizeof(UA_AggregateFilter), /* .memSize */
+ UA_TYPES_AGGREGATEFILTER, /* .typeIndex */
+ 4, /* .membersSize */
+ false, /* .builtin */
+ false, /* .pointerFree */
+ false, /* .overlayable */
+ 730, /* .binaryEncodingId */
+ AggregateFilter_members /* .members */
+},
+/* RegisterServerRequest */
+{
+ UA_TYPENAME("RegisterServerRequest") /* .typeName */
+ {0, UA_NODEIDTYPE_NUMERIC, {435}}, /* .typeId */
+ sizeof(UA_RegisterServerRequest), /* .memSize */
+ UA_TYPES_REGISTERSERVERREQUEST, /* .typeIndex */
+ 2, /* .membersSize */
+ false, /* .builtin */
+ false, /* .pointerFree */
+ false, /* .overlayable */
+ 437, /* .binaryEncodingId */
+ RegisterServerRequest_members /* .members */
+},
+/* EndpointDescription */
+{
+ UA_TYPENAME("EndpointDescription") /* .typeName */
+ {0, UA_NODEIDTYPE_NUMERIC, {312}}, /* .typeId */
+ sizeof(UA_EndpointDescription), /* .memSize */
+ UA_TYPES_ENDPOINTDESCRIPTION, /* .typeIndex */
+ 8, /* .membersSize */
+ false, /* .builtin */
+ false, /* .pointerFree */
+ false, /* .overlayable */
+ 314, /* .binaryEncodingId */
+ EndpointDescription_members /* .members */
+},
+/* CreateMonitoredItemsRequest */
+{
+ UA_TYPENAME("CreateMonitoredItemsRequest") /* .typeName */
+ {0, UA_NODEIDTYPE_NUMERIC, {749}}, /* .typeId */
+ sizeof(UA_CreateMonitoredItemsRequest), /* .memSize */
+ UA_TYPES_CREATEMONITOREDITEMSREQUEST, /* .typeIndex */
+ 4, /* .membersSize */
+ false, /* .builtin */
+ false, /* .pointerFree */
+ false, /* .overlayable */
+ 751, /* .binaryEncodingId */
+ CreateMonitoredItemsRequest_members /* .members */
+},
+/* ContentFilter */
+{
+ UA_TYPENAME("ContentFilter") /* .typeName */
+ {0, UA_NODEIDTYPE_NUMERIC, {586}}, /* .typeId */
+ sizeof(UA_ContentFilter), /* .memSize */
+ UA_TYPES_CONTENTFILTER, /* .typeIndex */
+ 1, /* .membersSize */
+ false, /* .builtin */
+ false, /* .pointerFree */
+ false, /* .overlayable */
+ 588, /* .binaryEncodingId */
+ ContentFilter_members /* .members */
+},
+/* QueryFirstResponse */
+{
+ UA_TYPENAME("QueryFirstResponse") /* .typeName */
+ {0, UA_NODEIDTYPE_NUMERIC, {616}}, /* .typeId */
+ sizeof(UA_QueryFirstResponse), /* .memSize */
+ UA_TYPES_QUERYFIRSTRESPONSE, /* .typeIndex */
+ 6, /* .membersSize */
+ false, /* .builtin */
+ false, /* .pointerFree */
+ false, /* .overlayable */
+ 618, /* .binaryEncodingId */
+ QueryFirstResponse_members /* .members */
+},
+/* AddNodesRequest */
+{
+ UA_TYPENAME("AddNodesRequest") /* .typeName */
+ {0, UA_NODEIDTYPE_NUMERIC, {486}}, /* .typeId */
+ sizeof(UA_AddNodesRequest), /* .memSize */
+ UA_TYPES_ADDNODESREQUEST, /* .typeIndex */
+ 2, /* .membersSize */
+ false, /* .builtin */
+ false, /* .pointerFree */
+ false, /* .overlayable */
+ 488, /* .binaryEncodingId */
+ AddNodesRequest_members /* .members */
+},
+/* BrowseRequest */
+{
+ UA_TYPENAME("BrowseRequest") /* .typeName */
+ {0, UA_NODEIDTYPE_NUMERIC, {525}}, /* .typeId */
+ sizeof(UA_BrowseRequest), /* .memSize */
+ UA_TYPES_BROWSEREQUEST, /* .typeIndex */
+ 4, /* .membersSize */
+ false, /* .builtin */
+ false, /* .pointerFree */
+ false, /* .overlayable */
+ 527, /* .binaryEncodingId */
+ BrowseRequest_members /* .members */
+},
+/* BrowseResult */
+{
+ UA_TYPENAME("BrowseResult") /* .typeName */
+ {0, UA_NODEIDTYPE_NUMERIC, {522}}, /* .typeId */
+ sizeof(UA_BrowseResult), /* .memSize */
+ UA_TYPES_BROWSERESULT, /* .typeIndex */
+ 3, /* .membersSize */
+ false, /* .builtin */
+ false, /* .pointerFree */
+ false, /* .overlayable */
+ 524, /* .binaryEncodingId */
+ BrowseResult_members /* .members */
+},
+/* RegisterServer2Request */
+{
+ UA_TYPENAME("RegisterServer2Request") /* .typeName */
+ {0, UA_NODEIDTYPE_NUMERIC, {12193}}, /* .typeId */
+ sizeof(UA_RegisterServer2Request), /* .memSize */
+ UA_TYPES_REGISTERSERVER2REQUEST, /* .typeIndex */
+ 3, /* .membersSize */
+ false, /* .builtin */
+ false, /* .pointerFree */
+ false, /* .overlayable */
+ 12211, /* .binaryEncodingId */
+ RegisterServer2Request_members /* .members */
+},
+/* CreateSessionRequest */
+{
+ UA_TYPENAME("CreateSessionRequest") /* .typeName */
+ {0, UA_NODEIDTYPE_NUMERIC, {459}}, /* .typeId */
+ sizeof(UA_CreateSessionRequest), /* .memSize */
+ UA_TYPES_CREATESESSIONREQUEST, /* .typeIndex */
+ 9, /* .membersSize */
+ false, /* .builtin */
+ false, /* .pointerFree */
+ false, /* .overlayable */
+ 461, /* .binaryEncodingId */
+ CreateSessionRequest_members /* .members */
+},
+/* EventFilter */
+{
+ UA_TYPENAME("EventFilter") /* .typeName */
+ {0, UA_NODEIDTYPE_NUMERIC, {725}}, /* .typeId */
+ sizeof(UA_EventFilter), /* .memSize */
+ UA_TYPES_EVENTFILTER, /* .typeIndex */
+ 2, /* .membersSize */
+ false, /* .builtin */
+ false, /* .pointerFree */
+ false, /* .overlayable */
+ 727, /* .binaryEncodingId */
+ EventFilter_members /* .members */
+},
+/* GetEndpointsResponse */
+{
+ UA_TYPENAME("GetEndpointsResponse") /* .typeName */
+ {0, UA_NODEIDTYPE_NUMERIC, {429}}, /* .typeId */
+ sizeof(UA_GetEndpointsResponse), /* .memSize */
+ UA_TYPES_GETENDPOINTSRESPONSE, /* .typeIndex */
+ 2, /* .membersSize */
+ false, /* .builtin */
+ false, /* .pointerFree */
+ false, /* .overlayable */
+ 431, /* .binaryEncodingId */
+ GetEndpointsResponse_members /* .members */
+},
+/* FindServersResponse */
+{
+ UA_TYPENAME("FindServersResponse") /* .typeName */
+ {0, UA_NODEIDTYPE_NUMERIC, {423}}, /* .typeId */
+ sizeof(UA_FindServersResponse), /* .memSize */
+ UA_TYPES_FINDSERVERSRESPONSE, /* .typeIndex */
+ 2, /* .membersSize */
+ false, /* .builtin */
+ false, /* .pointerFree */
+ false, /* .overlayable */
+ 425, /* .binaryEncodingId */
+ FindServersResponse_members /* .members */
+},
+/* BrowseNextResponse */
+{
+ UA_TYPENAME("BrowseNextResponse") /* .typeName */
+ {0, UA_NODEIDTYPE_NUMERIC, {534}}, /* .typeId */
+ sizeof(UA_BrowseNextResponse), /* .memSize */
+ UA_TYPES_BROWSENEXTRESPONSE, /* .typeIndex */
+ 3, /* .membersSize */
+ false, /* .builtin */
+ false, /* .pointerFree */
+ false, /* .overlayable */
+ 536, /* .binaryEncodingId */
+ BrowseNextResponse_members /* .members */
+},
+/* BrowseResponse */
+{
+ UA_TYPENAME("BrowseResponse") /* .typeName */
+ {0, UA_NODEIDTYPE_NUMERIC, {528}}, /* .typeId */
+ sizeof(UA_BrowseResponse), /* .memSize */
+ UA_TYPES_BROWSERESPONSE, /* .typeIndex */
+ 3, /* .membersSize */
+ false, /* .builtin */
+ false, /* .pointerFree */
+ false, /* .overlayable */
+ 530, /* .binaryEncodingId */
+ BrowseResponse_members /* .members */
+},
+/* CreateSessionResponse */
+{
+ UA_TYPENAME("CreateSessionResponse") /* .typeName */
+ {0, UA_NODEIDTYPE_NUMERIC, {462}}, /* .typeId */
+ sizeof(UA_CreateSessionResponse), /* .memSize */
+ UA_TYPES_CREATESESSIONRESPONSE, /* .typeIndex */
+ 10, /* .membersSize */
+ false, /* .builtin */
+ false, /* .pointerFree */
+ false, /* .overlayable */
+ 464, /* .binaryEncodingId */
+ CreateSessionResponse_members /* .members */
+},
+/* QueryFirstRequest */
+{
+ UA_TYPENAME("QueryFirstRequest") /* .typeName */
+ {0, UA_NODEIDTYPE_NUMERIC, {613}}, /* .typeId */
+ sizeof(UA_QueryFirstRequest), /* .memSize */
+ UA_TYPES_QUERYFIRSTREQUEST, /* .typeIndex */
+ 6, /* .membersSize */
+ false, /* .builtin */
+ false, /* .pointerFree */
+ false, /* .overlayable */
+ 615, /* .binaryEncodingId */
+ QueryFirstRequest_members /* .members */
+},
+};
+
+
+/*********************************** amalgamated original file "/home/jvoe/open62541/build/src_generated/ua_transport_generated.c" ***********************************/
+
+/* Generated from Opc.Ua.Types.bsd, Custom.Opc.Ua.Transport.bsd with script /home/jvoe/open62541/tools/generate_datatypes.py
+ * on host rigel by user jvoe at 2019-01-04 01:18:40 */
+
+
+/* SecureConversationMessageAbortBody */
+static UA_DataTypeMember SecureConversationMessageAbortBody_members[2] = {
+{
+ UA_TYPENAME("error") /* .memberName */
+ UA_TYPES_UINT32, /* .memberTypeIndex */
+ 0, /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("reason") /* .memberName */
+ UA_TYPES_STRING, /* .memberTypeIndex */
+ offsetof(UA_SecureConversationMessageAbortBody, reason) - offsetof(UA_SecureConversationMessageAbortBody, error) - sizeof(UA_UInt32), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+}};
+
+/* SecureConversationMessageFooter */
+static UA_DataTypeMember SecureConversationMessageFooter_members[2] = {
+{
+ UA_TYPENAME("padding") /* .memberName */
+ UA_TYPES_BYTE, /* .memberTypeIndex */
+ 0, /* .padding */
+ true, /* .namespaceZero */
+ true /* .isArray */
+},
+{
+ UA_TYPENAME("signature") /* .memberName */
+ UA_TYPES_BYTE, /* .memberTypeIndex */
+ offsetof(UA_SecureConversationMessageFooter, signature) - offsetof(UA_SecureConversationMessageFooter, padding) - sizeof(void*), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+}};
+
+/* TcpHelloMessage */
+static UA_DataTypeMember TcpHelloMessage_members[6] = {
+{
+ UA_TYPENAME("protocolVersion") /* .memberName */
+ UA_TYPES_UINT32, /* .memberTypeIndex */
+ 0, /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("receiveBufferSize") /* .memberName */
+ UA_TYPES_UINT32, /* .memberTypeIndex */
+ offsetof(UA_TcpHelloMessage, receiveBufferSize) - offsetof(UA_TcpHelloMessage, protocolVersion) - sizeof(UA_UInt32), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("sendBufferSize") /* .memberName */
+ UA_TYPES_UINT32, /* .memberTypeIndex */
+ offsetof(UA_TcpHelloMessage, sendBufferSize) - offsetof(UA_TcpHelloMessage, receiveBufferSize) - sizeof(UA_UInt32), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("maxMessageSize") /* .memberName */
+ UA_TYPES_UINT32, /* .memberTypeIndex */
+ offsetof(UA_TcpHelloMessage, maxMessageSize) - offsetof(UA_TcpHelloMessage, sendBufferSize) - sizeof(UA_UInt32), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("maxChunkCount") /* .memberName */
+ UA_TYPES_UINT32, /* .memberTypeIndex */
+ offsetof(UA_TcpHelloMessage, maxChunkCount) - offsetof(UA_TcpHelloMessage, maxMessageSize) - sizeof(UA_UInt32), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("endpointUrl") /* .memberName */
+ UA_TYPES_STRING, /* .memberTypeIndex */
+ offsetof(UA_TcpHelloMessage, endpointUrl) - offsetof(UA_TcpHelloMessage, maxChunkCount) - sizeof(UA_UInt32), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+}};
+
+/* TcpErrorMessage */
+static UA_DataTypeMember TcpErrorMessage_members[2] = {
+{
+ UA_TYPENAME("error") /* .memberName */
+ UA_TYPES_UINT32, /* .memberTypeIndex */
+ 0, /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("reason") /* .memberName */
+ UA_TYPES_STRING, /* .memberTypeIndex */
+ offsetof(UA_TcpErrorMessage, reason) - offsetof(UA_TcpErrorMessage, error) - sizeof(UA_UInt32), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+}};
+
+/* MessageType */
+static UA_DataTypeMember MessageType_members[1] = {
+{
+ UA_TYPENAME("") /* .memberName */
+ UA_TYPES_INT32, /* .memberTypeIndex */
+ 0, /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+}};
+
+/* AsymmetricAlgorithmSecurityHeader */
+static UA_DataTypeMember AsymmetricAlgorithmSecurityHeader_members[3] = {
+{
+ UA_TYPENAME("securityPolicyUri") /* .memberName */
+ UA_TYPES_BYTESTRING, /* .memberTypeIndex */
+ 0, /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("senderCertificate") /* .memberName */
+ UA_TYPES_BYTESTRING, /* .memberTypeIndex */
+ offsetof(UA_AsymmetricAlgorithmSecurityHeader, senderCertificate) - offsetof(UA_AsymmetricAlgorithmSecurityHeader, securityPolicyUri) - sizeof(UA_ByteString), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("receiverCertificateThumbprint") /* .memberName */
+ UA_TYPES_BYTESTRING, /* .memberTypeIndex */
+ offsetof(UA_AsymmetricAlgorithmSecurityHeader, receiverCertificateThumbprint) - offsetof(UA_AsymmetricAlgorithmSecurityHeader, senderCertificate) - sizeof(UA_ByteString), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+}};
+
+/* TcpAcknowledgeMessage */
+static UA_DataTypeMember TcpAcknowledgeMessage_members[5] = {
+{
+ UA_TYPENAME("protocolVersion") /* .memberName */
+ UA_TYPES_UINT32, /* .memberTypeIndex */
+ 0, /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("receiveBufferSize") /* .memberName */
+ UA_TYPES_UINT32, /* .memberTypeIndex */
+ offsetof(UA_TcpAcknowledgeMessage, receiveBufferSize) - offsetof(UA_TcpAcknowledgeMessage, protocolVersion) - sizeof(UA_UInt32), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("sendBufferSize") /* .memberName */
+ UA_TYPES_UINT32, /* .memberTypeIndex */
+ offsetof(UA_TcpAcknowledgeMessage, sendBufferSize) - offsetof(UA_TcpAcknowledgeMessage, receiveBufferSize) - sizeof(UA_UInt32), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("maxMessageSize") /* .memberName */
+ UA_TYPES_UINT32, /* .memberTypeIndex */
+ offsetof(UA_TcpAcknowledgeMessage, maxMessageSize) - offsetof(UA_TcpAcknowledgeMessage, sendBufferSize) - sizeof(UA_UInt32), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("maxChunkCount") /* .memberName */
+ UA_TYPES_UINT32, /* .memberTypeIndex */
+ offsetof(UA_TcpAcknowledgeMessage, maxChunkCount) - offsetof(UA_TcpAcknowledgeMessage, maxMessageSize) - sizeof(UA_UInt32), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+}};
+
+/* SequenceHeader */
+static UA_DataTypeMember SequenceHeader_members[2] = {
+{
+ UA_TYPENAME("sequenceNumber") /* .memberName */
+ UA_TYPES_UINT32, /* .memberTypeIndex */
+ 0, /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("requestId") /* .memberName */
+ UA_TYPES_UINT32, /* .memberTypeIndex */
+ offsetof(UA_SequenceHeader, requestId) - offsetof(UA_SequenceHeader, sequenceNumber) - sizeof(UA_UInt32), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+}};
+
+/* TcpMessageHeader */
+static UA_DataTypeMember TcpMessageHeader_members[2] = {
+{
+ UA_TYPENAME("messageTypeAndChunkType") /* .memberName */
+ UA_TYPES_UINT32, /* .memberTypeIndex */
+ 0, /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("messageSize") /* .memberName */
+ UA_TYPES_UINT32, /* .memberTypeIndex */
+ offsetof(UA_TcpMessageHeader, messageSize) - offsetof(UA_TcpMessageHeader, messageTypeAndChunkType) - sizeof(UA_UInt32), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+}};
+
+/* ChunkType */
+static UA_DataTypeMember ChunkType_members[1] = {
+{
+ UA_TYPENAME("") /* .memberName */
+ UA_TYPES_INT32, /* .memberTypeIndex */
+ 0, /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+}};
+
+/* SymmetricAlgorithmSecurityHeader */
+static UA_DataTypeMember SymmetricAlgorithmSecurityHeader_members[1] = {
+{
+ UA_TYPENAME("tokenId") /* .memberName */
+ UA_TYPES_UINT32, /* .memberTypeIndex */
+ 0, /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+}};
+
+/* SecureConversationMessageHeader */
+static UA_DataTypeMember SecureConversationMessageHeader_members[2] = {
+{
+ UA_TYPENAME("messageHeader") /* .memberName */
+ UA_TRANSPORT_TCPMESSAGEHEADER, /* .memberTypeIndex */
+ 0, /* .padding */
+ false, /* .namespaceZero */
+ false /* .isArray */
+},
+{
+ UA_TYPENAME("secureChannelId") /* .memberName */
+ UA_TYPES_UINT32, /* .memberTypeIndex */
+ offsetof(UA_SecureConversationMessageHeader, secureChannelId) - offsetof(UA_SecureConversationMessageHeader, messageHeader) - sizeof(UA_TcpMessageHeader), /* .padding */
+ true, /* .namespaceZero */
+ false /* .isArray */
+}};
+const UA_DataType UA_TRANSPORT[UA_TRANSPORT_COUNT] = {
+/* SecureConversationMessageAbortBody */
+{
+ UA_TYPENAME("SecureConversationMessageAbortBody") /* .typeName */
+ {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .typeId */
+ sizeof(UA_SecureConversationMessageAbortBody), /* .memSize */
+ UA_TRANSPORT_SECURECONVERSATIONMESSAGEABORTBODY, /* .typeIndex */
+ 2, /* .membersSize */
+ false, /* .builtin */
+ false, /* .pointerFree */
+ false, /* .overlayable */
+ 0, /* .binaryEncodingId */
+ SecureConversationMessageAbortBody_members /* .members */
+},
+/* SecureConversationMessageFooter */
+{
+ UA_TYPENAME("SecureConversationMessageFooter") /* .typeName */
+ {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .typeId */
+ sizeof(UA_SecureConversationMessageFooter), /* .memSize */
+ UA_TRANSPORT_SECURECONVERSATIONMESSAGEFOOTER, /* .typeIndex */
+ 2, /* .membersSize */
+ false, /* .builtin */
+ false, /* .pointerFree */
+ false, /* .overlayable */
+ 0, /* .binaryEncodingId */
+ SecureConversationMessageFooter_members /* .members */
+},
+/* TcpHelloMessage */
+{
+ UA_TYPENAME("TcpHelloMessage") /* .typeName */
+ {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .typeId */
+ sizeof(UA_TcpHelloMessage), /* .memSize */
+ UA_TRANSPORT_TCPHELLOMESSAGE, /* .typeIndex */
+ 6, /* .membersSize */
+ false, /* .builtin */
+ false, /* .pointerFree */
+ false, /* .overlayable */
+ 0, /* .binaryEncodingId */
+ TcpHelloMessage_members /* .members */
+},
+/* TcpErrorMessage */
+{
+ UA_TYPENAME("TcpErrorMessage") /* .typeName */
+ {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .typeId */
+ sizeof(UA_TcpErrorMessage), /* .memSize */
+ UA_TRANSPORT_TCPERRORMESSAGE, /* .typeIndex */
+ 2, /* .membersSize */
+ false, /* .builtin */
+ false, /* .pointerFree */
+ false, /* .overlayable */
+ 0, /* .binaryEncodingId */
+ TcpErrorMessage_members /* .members */
+},
+/* MessageType */
+{
+ UA_TYPENAME("MessageType") /* .typeName */
+ {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .typeId */
+ sizeof(UA_MessageType), /* .memSize */
+ UA_TYPES_INT32, /* .typeIndex */
+ 1, /* .membersSize */
+ true, /* .builtin */
+ true, /* .pointerFree */
+ UA_BINARY_OVERLAYABLE_INTEGER, /* .overlayable */
+ 0, /* .binaryEncodingId */
+ MessageType_members /* .members */
+},
+/* AsymmetricAlgorithmSecurityHeader */
+{
+ UA_TYPENAME("AsymmetricAlgorithmSecurityHeader") /* .typeName */
+ {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .typeId */
+ sizeof(UA_AsymmetricAlgorithmSecurityHeader), /* .memSize */
+ UA_TRANSPORT_ASYMMETRICALGORITHMSECURITYHEADER, /* .typeIndex */
+ 3, /* .membersSize */
+ false, /* .builtin */
+ false, /* .pointerFree */
+ false, /* .overlayable */
+ 0, /* .binaryEncodingId */
+ AsymmetricAlgorithmSecurityHeader_members /* .members */
+},
+/* TcpAcknowledgeMessage */
+{
+ UA_TYPENAME("TcpAcknowledgeMessage") /* .typeName */
+ {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .typeId */
+ sizeof(UA_TcpAcknowledgeMessage), /* .memSize */
+ UA_TRANSPORT_TCPACKNOWLEDGEMESSAGE, /* .typeIndex */
+ 5, /* .membersSize */
+ false, /* .builtin */
+ true, /* .pointerFree */
+ true
+ && UA_BINARY_OVERLAYABLE_INTEGER
+ && UA_BINARY_OVERLAYABLE_INTEGER
+ && offsetof(UA_TcpAcknowledgeMessage, receiveBufferSize) == (offsetof(UA_TcpAcknowledgeMessage, protocolVersion) + sizeof(UA_UInt32))
+ && UA_BINARY_OVERLAYABLE_INTEGER
+ && offsetof(UA_TcpAcknowledgeMessage, sendBufferSize) == (offsetof(UA_TcpAcknowledgeMessage, receiveBufferSize) + sizeof(UA_UInt32))
+ && UA_BINARY_OVERLAYABLE_INTEGER
+ && offsetof(UA_TcpAcknowledgeMessage, maxMessageSize) == (offsetof(UA_TcpAcknowledgeMessage, sendBufferSize) + sizeof(UA_UInt32))
+ && UA_BINARY_OVERLAYABLE_INTEGER
+ && offsetof(UA_TcpAcknowledgeMessage, maxChunkCount) == (offsetof(UA_TcpAcknowledgeMessage, maxMessageSize) + sizeof(UA_UInt32)), /* .overlayable */
+ 0, /* .binaryEncodingId */
+ TcpAcknowledgeMessage_members /* .members */
+},
+/* SequenceHeader */
+{
+ UA_TYPENAME("SequenceHeader") /* .typeName */
+ {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .typeId */
+ sizeof(UA_SequenceHeader), /* .memSize */
+ UA_TRANSPORT_SEQUENCEHEADER, /* .typeIndex */
+ 2, /* .membersSize */
+ false, /* .builtin */
+ true, /* .pointerFree */
+ true
+ && UA_BINARY_OVERLAYABLE_INTEGER
+ && UA_BINARY_OVERLAYABLE_INTEGER
+ && offsetof(UA_SequenceHeader, requestId) == (offsetof(UA_SequenceHeader, sequenceNumber) + sizeof(UA_UInt32)), /* .overlayable */
+ 0, /* .binaryEncodingId */
+ SequenceHeader_members /* .members */
+},
+/* TcpMessageHeader */
+{
+ UA_TYPENAME("TcpMessageHeader") /* .typeName */
+ {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .typeId */
+ sizeof(UA_TcpMessageHeader), /* .memSize */
+ UA_TRANSPORT_TCPMESSAGEHEADER, /* .typeIndex */
+ 2, /* .membersSize */
+ false, /* .builtin */
+ true, /* .pointerFree */
+ true
+ && UA_BINARY_OVERLAYABLE_INTEGER
+ && UA_BINARY_OVERLAYABLE_INTEGER
+ && offsetof(UA_TcpMessageHeader, messageSize) == (offsetof(UA_TcpMessageHeader, messageTypeAndChunkType) + sizeof(UA_UInt32)), /* .overlayable */
+ 0, /* .binaryEncodingId */
+ TcpMessageHeader_members /* .members */
+},
+/* ChunkType */
+{
+ UA_TYPENAME("ChunkType") /* .typeName */
+ {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .typeId */
+ sizeof(UA_ChunkType), /* .memSize */
+ UA_TYPES_INT32, /* .typeIndex */
+ 1, /* .membersSize */
+ true, /* .builtin */
+ true, /* .pointerFree */
+ UA_BINARY_OVERLAYABLE_INTEGER, /* .overlayable */
+ 0, /* .binaryEncodingId */
+ ChunkType_members /* .members */
+},
+/* SymmetricAlgorithmSecurityHeader */
+{
+ UA_TYPENAME("SymmetricAlgorithmSecurityHeader") /* .typeName */
+ {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .typeId */
+ sizeof(UA_SymmetricAlgorithmSecurityHeader), /* .memSize */
+ UA_TRANSPORT_SYMMETRICALGORITHMSECURITYHEADER, /* .typeIndex */
+ 1, /* .membersSize */
+ false, /* .builtin */
+ true, /* .pointerFree */
+ true
+ && UA_BINARY_OVERLAYABLE_INTEGER, /* .overlayable */
+ 0, /* .binaryEncodingId */
+ SymmetricAlgorithmSecurityHeader_members /* .members */
+},
+/* SecureConversationMessageHeader */
+{
+ UA_TYPENAME("SecureConversationMessageHeader") /* .typeName */
+ {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .typeId */
+ sizeof(UA_SecureConversationMessageHeader), /* .memSize */
+ UA_TRANSPORT_SECURECONVERSATIONMESSAGEHEADER, /* .typeIndex */
+ 2, /* .membersSize */
+ false, /* .builtin */
+ true, /* .pointerFree */
+ true
+ && true
+ && UA_BINARY_OVERLAYABLE_INTEGER
+ && UA_BINARY_OVERLAYABLE_INTEGER
+ && offsetof(UA_TcpMessageHeader, messageSize) == (offsetof(UA_TcpMessageHeader, messageTypeAndChunkType) + sizeof(UA_UInt32))
+ && UA_BINARY_OVERLAYABLE_INTEGER
+ && offsetof(UA_SecureConversationMessageHeader, secureChannelId) == (offsetof(UA_SecureConversationMessageHeader, messageHeader) + sizeof(UA_TcpMessageHeader)), /* .overlayable */
+ 0, /* .binaryEncodingId */
+ SecureConversationMessageHeader_members /* .members */
+},
+};
+
+
+/*********************************** amalgamated original file "/home/jvoe/open62541/build/src_generated/ua_statuscode_descriptions.c" ***********************************/
+
+/**********************************************************
+ * Autogenerated -- do not modify
+ * Generated from /home/jvoe/open62541/tools/schema/Opc.Ua.StatusCodes.csv with script /home/jvoe/open62541/tools/generate_statuscode_descriptions.py
+ *********************************************************/
+
+
+
+/* Definition for the deprecated StatusCode description API */
+const UA_StatusCodeDescription statusCodeExplanation_default = {0xffffffff, "", ""};
+
+typedef struct {
+ UA_StatusCode code;
+ const char *name;
+} UA_StatusCodeName;
+
+#ifndef UA_ENABLE_STATUSCODE_DESCRIPTIONS
+static const char * emptyStatusCodeName = "";
+const char * UA_StatusCode_name(UA_StatusCode code) {
+ return emptyStatusCodeName;
+}
+#else
+static const size_t statusCodeDescriptionsSize = 229;
+static const UA_StatusCodeName statusCodeDescriptions[229] = {
+ {UA_STATUSCODE_GOOD, "Good"},
+
+ {UA_STATUSCODE_BADUNEXPECTEDERROR, "BadUnexpectedError"},
+ {UA_STATUSCODE_BADINTERNALERROR, "BadInternalError"},
+ {UA_STATUSCODE_BADOUTOFMEMORY, "BadOutOfMemory"},
+ {UA_STATUSCODE_BADRESOURCEUNAVAILABLE, "BadResourceUnavailable"},
+ {UA_STATUSCODE_BADCOMMUNICATIONERROR, "BadCommunicationError"},
+ {UA_STATUSCODE_BADENCODINGERROR, "BadEncodingError"},
+ {UA_STATUSCODE_BADDECODINGERROR, "BadDecodingError"},
+ {UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED, "BadEncodingLimitsExceeded"},
+ {UA_STATUSCODE_BADREQUESTTOOLARGE, "BadRequestTooLarge"},
+ {UA_STATUSCODE_BADRESPONSETOOLARGE, "BadResponseTooLarge"},
+ {UA_STATUSCODE_BADUNKNOWNRESPONSE, "BadUnknownResponse"},
+ {UA_STATUSCODE_BADTIMEOUT, "BadTimeout"},
+ {UA_STATUSCODE_BADSERVICEUNSUPPORTED, "BadServiceUnsupported"},
+ {UA_STATUSCODE_BADSHUTDOWN, "BadShutdown"},
+ {UA_STATUSCODE_BADSERVERNOTCONNECTED, "BadServerNotConnected"},
+ {UA_STATUSCODE_BADSERVERHALTED, "BadServerHalted"},
+ {UA_STATUSCODE_BADNOTHINGTODO, "BadNothingToDo"},
+ {UA_STATUSCODE_BADTOOMANYOPERATIONS, "BadTooManyOperations"},
+ {UA_STATUSCODE_BADTOOMANYMONITOREDITEMS, "BadTooManyMonitoredItems"},
+ {UA_STATUSCODE_BADDATATYPEIDUNKNOWN, "BadDataTypeIdUnknown"},
+ {UA_STATUSCODE_BADCERTIFICATEINVALID, "BadCertificateInvalid"},
+ {UA_STATUSCODE_BADSECURITYCHECKSFAILED, "BadSecurityChecksFailed"},
+ {UA_STATUSCODE_BADCERTIFICATETIMEINVALID, "BadCertificateTimeInvalid"},
+ {UA_STATUSCODE_BADCERTIFICATEISSUERTIMEINVALID, "BadCertificateIssuerTimeInvalid"},
+ {UA_STATUSCODE_BADCERTIFICATEHOSTNAMEINVALID, "BadCertificateHostNameInvalid"},
+ {UA_STATUSCODE_BADCERTIFICATEURIINVALID, "BadCertificateUriInvalid"},
+ {UA_STATUSCODE_BADCERTIFICATEUSENOTALLOWED, "BadCertificateUseNotAllowed"},
+ {UA_STATUSCODE_BADCERTIFICATEISSUERUSENOTALLOWED, "BadCertificateIssuerUseNotAllowed"},
+ {UA_STATUSCODE_BADCERTIFICATEUNTRUSTED, "BadCertificateUntrusted"},
+ {UA_STATUSCODE_BADCERTIFICATEREVOCATIONUNKNOWN, "BadCertificateRevocationUnknown"},
+ {UA_STATUSCODE_BADCERTIFICATEISSUERREVOCATIONUNKNOWN, "BadCertificateIssuerRevocationUnknown"},
+ {UA_STATUSCODE_BADCERTIFICATEREVOKED, "BadCertificateRevoked"},
+ {UA_STATUSCODE_BADCERTIFICATEISSUERREVOKED, "BadCertificateIssuerRevoked"},
+ {UA_STATUSCODE_BADCERTIFICATECHAININCOMPLETE, "BadCertificateChainIncomplete"},
+ {UA_STATUSCODE_BADUSERACCESSDENIED, "BadUserAccessDenied"},
+ {UA_STATUSCODE_BADIDENTITYTOKENINVALID, "BadIdentityTokenInvalid"},
+ {UA_STATUSCODE_BADIDENTITYTOKENREJECTED, "BadIdentityTokenRejected"},
+ {UA_STATUSCODE_BADSECURECHANNELIDINVALID, "BadSecureChannelIdInvalid"},
+ {UA_STATUSCODE_BADINVALIDTIMESTAMP, "BadInvalidTimestamp"},
+ {UA_STATUSCODE_BADNONCEINVALID, "BadNonceInvalid"},
+ {UA_STATUSCODE_BADSESSIONIDINVALID, "BadSessionIdInvalid"},
+ {UA_STATUSCODE_BADSESSIONCLOSED, "BadSessionClosed"},
+ {UA_STATUSCODE_BADSESSIONNOTACTIVATED, "BadSessionNotActivated"},
+ {UA_STATUSCODE_BADSUBSCRIPTIONIDINVALID, "BadSubscriptionIdInvalid"},
+ {UA_STATUSCODE_BADREQUESTHEADERINVALID, "BadRequestHeaderInvalid"},
+ {UA_STATUSCODE_BADTIMESTAMPSTORETURNINVALID, "BadTimestampsToReturnInvalid"},
+ {UA_STATUSCODE_BADREQUESTCANCELLEDBYCLIENT, "BadRequestCancelledByClient"},
+ {UA_STATUSCODE_BADTOOMANYARGUMENTS, "BadTooManyArguments"},
+ {UA_STATUSCODE_GOODSUBSCRIPTIONTRANSFERRED, "GoodSubscriptionTransferred"},
+ {UA_STATUSCODE_GOODCOMPLETESASYNCHRONOUSLY, "GoodCompletesAsynchronously"},
+ {UA_STATUSCODE_GOODOVERLOAD, "GoodOverload"},
+ {UA_STATUSCODE_GOODCLAMPED, "GoodClamped"},
+ {UA_STATUSCODE_BADNOCOMMUNICATION, "BadNoCommunication"},
+ {UA_STATUSCODE_BADWAITINGFORINITIALDATA, "BadWaitingForInitialData"},
+ {UA_STATUSCODE_BADNODEIDINVALID, "BadNodeIdInvalid"},
+ {UA_STATUSCODE_BADNODEIDUNKNOWN, "BadNodeIdUnknown"},
+ {UA_STATUSCODE_BADATTRIBUTEIDINVALID, "BadAttributeIdInvalid"},
+ {UA_STATUSCODE_BADINDEXRANGEINVALID, "BadIndexRangeInvalid"},
+ {UA_STATUSCODE_BADINDEXRANGENODATA, "BadIndexRangeNoData"},
+ {UA_STATUSCODE_BADDATAENCODINGINVALID, "BadDataEncodingInvalid"},
+ {UA_STATUSCODE_BADDATAENCODINGUNSUPPORTED, "BadDataEncodingUnsupported"},
+ {UA_STATUSCODE_BADNOTREADABLE, "BadNotReadable"},
+ {UA_STATUSCODE_BADNOTWRITABLE, "BadNotWritable"},
+ {UA_STATUSCODE_BADOUTOFRANGE, "BadOutOfRange"},
+ {UA_STATUSCODE_BADNOTSUPPORTED, "BadNotSupported"},
+ {UA_STATUSCODE_BADNOTFOUND, "BadNotFound"},
+ {UA_STATUSCODE_BADOBJECTDELETED, "BadObjectDeleted"},
+ {UA_STATUSCODE_BADNOTIMPLEMENTED, "BadNotImplemented"},
+ {UA_STATUSCODE_BADMONITORINGMODEINVALID, "BadMonitoringModeInvalid"},
+ {UA_STATUSCODE_BADMONITOREDITEMIDINVALID, "BadMonitoredItemIdInvalid"},
+ {UA_STATUSCODE_BADMONITOREDITEMFILTERINVALID, "BadMonitoredItemFilterInvalid"},
+ {UA_STATUSCODE_BADMONITOREDITEMFILTERUNSUPPORTED, "BadMonitoredItemFilterUnsupported"},
+ {UA_STATUSCODE_BADFILTERNOTALLOWED, "BadFilterNotAllowed"},
+ {UA_STATUSCODE_BADSTRUCTUREMISSING, "BadStructureMissing"},
+ {UA_STATUSCODE_BADEVENTFILTERINVALID, "BadEventFilterInvalid"},
+ {UA_STATUSCODE_BADCONTENTFILTERINVALID, "BadContentFilterInvalid"},
+ {UA_STATUSCODE_BADFILTEROPERATORINVALID, "BadFilterOperatorInvalid"},
+ {UA_STATUSCODE_BADFILTEROPERATORUNSUPPORTED, "BadFilterOperatorUnsupported"},
+ {UA_STATUSCODE_BADFILTEROPERANDCOUNTMISMATCH, "BadFilterOperandCountMismatch"},
+ {UA_STATUSCODE_BADFILTEROPERANDINVALID, "BadFilterOperandInvalid"},
+ {UA_STATUSCODE_BADFILTERELEMENTINVALID, "BadFilterElementInvalid"},
+ {UA_STATUSCODE_BADFILTERLITERALINVALID, "BadFilterLiteralInvalid"},
+ {UA_STATUSCODE_BADCONTINUATIONPOINTINVALID, "BadContinuationPointInvalid"},
+ {UA_STATUSCODE_BADNOCONTINUATIONPOINTS, "BadNoContinuationPoints"},
+ {UA_STATUSCODE_BADREFERENCETYPEIDINVALID, "BadReferenceTypeIdInvalid"},
+ {UA_STATUSCODE_BADBROWSEDIRECTIONINVALID, "BadBrowseDirectionInvalid"},
+ {UA_STATUSCODE_BADNODENOTINVIEW, "BadNodeNotInView"},
+ {UA_STATUSCODE_BADSERVERURIINVALID, "BadServerUriInvalid"},
+ {UA_STATUSCODE_BADSERVERNAMEMISSING, "BadServerNameMissing"},
+ {UA_STATUSCODE_BADDISCOVERYURLMISSING, "BadDiscoveryUrlMissing"},
+ {UA_STATUSCODE_BADSEMPAHOREFILEMISSING, "BadSempahoreFileMissing"},
+ {UA_STATUSCODE_BADREQUESTTYPEINVALID, "BadRequestTypeInvalid"},
+ {UA_STATUSCODE_BADSECURITYMODEREJECTED, "BadSecurityModeRejected"},
+ {UA_STATUSCODE_BADSECURITYPOLICYREJECTED, "BadSecurityPolicyRejected"},
+ {UA_STATUSCODE_BADTOOMANYSESSIONS, "BadTooManySessions"},
+ {UA_STATUSCODE_BADUSERSIGNATUREINVALID, "BadUserSignatureInvalid"},
+ {UA_STATUSCODE_BADAPPLICATIONSIGNATUREINVALID, "BadApplicationSignatureInvalid"},
+ {UA_STATUSCODE_BADNOVALIDCERTIFICATES, "BadNoValidCertificates"},
+ {UA_STATUSCODE_BADIDENTITYCHANGENOTSUPPORTED, "BadIdentityChangeNotSupported"},
+ {UA_STATUSCODE_BADREQUESTCANCELLEDBYREQUEST, "BadRequestCancelledByRequest"},
+ {UA_STATUSCODE_BADPARENTNODEIDINVALID, "BadParentNodeIdInvalid"},
+ {UA_STATUSCODE_BADREFERENCENOTALLOWED, "BadReferenceNotAllowed"},
+ {UA_STATUSCODE_BADNODEIDREJECTED, "BadNodeIdRejected"},
+ {UA_STATUSCODE_BADNODEIDEXISTS, "BadNodeIdExists"},
+ {UA_STATUSCODE_BADNODECLASSINVALID, "BadNodeClassInvalid"},
+ {UA_STATUSCODE_BADBROWSENAMEINVALID, "BadBrowseNameInvalid"},
+ {UA_STATUSCODE_BADBROWSENAMEDUPLICATED, "BadBrowseNameDuplicated"},
+ {UA_STATUSCODE_BADNODEATTRIBUTESINVALID, "BadNodeAttributesInvalid"},
+ {UA_STATUSCODE_BADTYPEDEFINITIONINVALID, "BadTypeDefinitionInvalid"},
+ {UA_STATUSCODE_BADSOURCENODEIDINVALID, "BadSourceNodeIdInvalid"},
+ {UA_STATUSCODE_BADTARGETNODEIDINVALID, "BadTargetNodeIdInvalid"},
+ {UA_STATUSCODE_BADDUPLICATEREFERENCENOTALLOWED, "BadDuplicateReferenceNotAllowed"},
+ {UA_STATUSCODE_BADINVALIDSELFREFERENCE, "BadInvalidSelfReference"},
+ {UA_STATUSCODE_BADREFERENCELOCALONLY, "BadReferenceLocalOnly"},
+ {UA_STATUSCODE_BADNODELETERIGHTS, "BadNoDeleteRights"},
+ {UA_STATUSCODE_UNCERTAINREFERENCENOTDELETED, "UncertainReferenceNotDeleted"},
+ {UA_STATUSCODE_BADSERVERINDEXINVALID, "BadServerIndexInvalid"},
+ {UA_STATUSCODE_BADVIEWIDUNKNOWN, "BadViewIdUnknown"},
+ {UA_STATUSCODE_BADVIEWTIMESTAMPINVALID, "BadViewTimestampInvalid"},
+ {UA_STATUSCODE_BADVIEWPARAMETERMISMATCH, "BadViewParameterMismatch"},
+ {UA_STATUSCODE_BADVIEWVERSIONINVALID, "BadViewVersionInvalid"},
+ {UA_STATUSCODE_UNCERTAINNOTALLNODESAVAILABLE, "UncertainNotAllNodesAvailable"},
+ {UA_STATUSCODE_GOODRESULTSMAYBEINCOMPLETE, "GoodResultsMayBeIncomplete"},
+ {UA_STATUSCODE_BADNOTTYPEDEFINITION, "BadNotTypeDefinition"},
+ {UA_STATUSCODE_UNCERTAINREFERENCEOUTOFSERVER, "UncertainReferenceOutOfServer"},
+ {UA_STATUSCODE_BADTOOMANYMATCHES, "BadTooManyMatches"},
+ {UA_STATUSCODE_BADQUERYTOOCOMPLEX, "BadQueryTooComplex"},
+ {UA_STATUSCODE_BADNOMATCH, "BadNoMatch"},
+ {UA_STATUSCODE_BADMAXAGEINVALID, "BadMaxAgeInvalid"},
+ {UA_STATUSCODE_BADSECURITYMODEINSUFFICIENT, "BadSecurityModeInsufficient"},
+ {UA_STATUSCODE_BADHISTORYOPERATIONINVALID, "BadHistoryOperationInvalid"},
+ {UA_STATUSCODE_BADHISTORYOPERATIONUNSUPPORTED, "BadHistoryOperationUnsupported"},
+ {UA_STATUSCODE_BADINVALIDTIMESTAMPARGUMENT, "BadInvalidTimestampArgument"},
+ {UA_STATUSCODE_BADWRITENOTSUPPORTED, "BadWriteNotSupported"},
+ {UA_STATUSCODE_BADTYPEMISMATCH, "BadTypeMismatch"},
+ {UA_STATUSCODE_BADMETHODINVALID, "BadMethodInvalid"},
+ {UA_STATUSCODE_BADARGUMENTSMISSING, "BadArgumentsMissing"},
+ {UA_STATUSCODE_BADTOOMANYSUBSCRIPTIONS, "BadTooManySubscriptions"},
+ {UA_STATUSCODE_BADTOOMANYPUBLISHREQUESTS, "BadTooManyPublishRequests"},
+ {UA_STATUSCODE_BADNOSUBSCRIPTION, "BadNoSubscription"},
+ {UA_STATUSCODE_BADSEQUENCENUMBERUNKNOWN, "BadSequenceNumberUnknown"},
+ {UA_STATUSCODE_BADMESSAGENOTAVAILABLE, "BadMessageNotAvailable"},
+ {UA_STATUSCODE_BADINSUFFICIENTCLIENTPROFILE, "BadInsufficientClientProfile"},
+ {UA_STATUSCODE_BADSTATENOTACTIVE, "BadStateNotActive"},
+ {UA_STATUSCODE_BADTCPSERVERTOOBUSY, "BadTcpServerTooBusy"},
+ {UA_STATUSCODE_BADTCPMESSAGETYPEINVALID, "BadTcpMessageTypeInvalid"},
+ {UA_STATUSCODE_BADTCPSECURECHANNELUNKNOWN, "BadTcpSecureChannelUnknown"},
+ {UA_STATUSCODE_BADTCPMESSAGETOOLARGE, "BadTcpMessageTooLarge"},
+ {UA_STATUSCODE_BADTCPNOTENOUGHRESOURCES, "BadTcpNotEnoughResources"},
+ {UA_STATUSCODE_BADTCPINTERNALERROR, "BadTcpInternalError"},
+ {UA_STATUSCODE_BADTCPENDPOINTURLINVALID, "BadTcpEndpointUrlInvalid"},
+ {UA_STATUSCODE_BADREQUESTINTERRUPTED, "BadRequestInterrupted"},
+ {UA_STATUSCODE_BADREQUESTTIMEOUT, "BadRequestTimeout"},
+ {UA_STATUSCODE_BADSECURECHANNELCLOSED, "BadSecureChannelClosed"},
+ {UA_STATUSCODE_BADSECURECHANNELTOKENUNKNOWN, "BadSecureChannelTokenUnknown"},
+ {UA_STATUSCODE_BADSEQUENCENUMBERINVALID, "BadSequenceNumberInvalid"},
+ {UA_STATUSCODE_BADPROTOCOLVERSIONUNSUPPORTED, "BadProtocolVersionUnsupported"},
+ {UA_STATUSCODE_BADCONFIGURATIONERROR, "BadConfigurationError"},
+ {UA_STATUSCODE_BADNOTCONNECTED, "BadNotConnected"},
+ {UA_STATUSCODE_BADDEVICEFAILURE, "BadDeviceFailure"},
+ {UA_STATUSCODE_BADSENSORFAILURE, "BadSensorFailure"},
+ {UA_STATUSCODE_BADOUTOFSERVICE, "BadOutOfService"},
+ {UA_STATUSCODE_BADDEADBANDFILTERINVALID, "BadDeadbandFilterInvalid"},
+ {UA_STATUSCODE_UNCERTAINNOCOMMUNICATIONLASTUSABLEVALUE, "UncertainNoCommunicationLastUsableValue"},
+ {UA_STATUSCODE_UNCERTAINLASTUSABLEVALUE, "UncertainLastUsableValue"},
+ {UA_STATUSCODE_UNCERTAINSUBSTITUTEVALUE, "UncertainSubstituteValue"},
+ {UA_STATUSCODE_UNCERTAININITIALVALUE, "UncertainInitialValue"},
+ {UA_STATUSCODE_UNCERTAINSENSORNOTACCURATE, "UncertainSensorNotAccurate"},
+ {UA_STATUSCODE_UNCERTAINENGINEERINGUNITSEXCEEDED, "UncertainEngineeringUnitsExceeded"},
+ {UA_STATUSCODE_UNCERTAINSUBNORMAL, "UncertainSubNormal"},
+ {UA_STATUSCODE_GOODLOCALOVERRIDE, "GoodLocalOverride"},
+ {UA_STATUSCODE_BADREFRESHINPROGRESS, "BadRefreshInProgress"},
+ {UA_STATUSCODE_BADCONDITIONALREADYDISABLED, "BadConditionAlreadyDisabled"},
+ {UA_STATUSCODE_BADCONDITIONALREADYENABLED, "BadConditionAlreadyEnabled"},
+ {UA_STATUSCODE_BADCONDITIONDISABLED, "BadConditionDisabled"},
+ {UA_STATUSCODE_BADEVENTIDUNKNOWN, "BadEventIdUnknown"},
+ {UA_STATUSCODE_BADEVENTNOTACKNOWLEDGEABLE, "BadEventNotAcknowledgeable"},
+ {UA_STATUSCODE_BADDIALOGNOTACTIVE, "BadDialogNotActive"},
+ {UA_STATUSCODE_BADDIALOGRESPONSEINVALID, "BadDialogResponseInvalid"},
+ {UA_STATUSCODE_BADCONDITIONBRANCHALREADYACKED, "BadConditionBranchAlreadyAcked"},
+ {UA_STATUSCODE_BADCONDITIONBRANCHALREADYCONFIRMED, "BadConditionBranchAlreadyConfirmed"},
+ {UA_STATUSCODE_BADCONDITIONALREADYSHELVED, "BadConditionAlreadyShelved"},
+ {UA_STATUSCODE_BADCONDITIONNOTSHELVED, "BadConditionNotShelved"},
+ {UA_STATUSCODE_BADSHELVINGTIMEOUTOFRANGE, "BadShelvingTimeOutOfRange"},
+ {UA_STATUSCODE_BADNODATA, "BadNoData"},
+ {UA_STATUSCODE_BADBOUNDNOTFOUND, "BadBoundNotFound"},
+ {UA_STATUSCODE_BADBOUNDNOTSUPPORTED, "BadBoundNotSupported"},
+ {UA_STATUSCODE_BADDATALOST, "BadDataLost"},
+ {UA_STATUSCODE_BADDATAUNAVAILABLE, "BadDataUnavailable"},
+ {UA_STATUSCODE_BADENTRYEXISTS, "BadEntryExists"},
+ {UA_STATUSCODE_BADNOENTRYEXISTS, "BadNoEntryExists"},
+ {UA_STATUSCODE_BADTIMESTAMPNOTSUPPORTED, "BadTimestampNotSupported"},
+ {UA_STATUSCODE_GOODENTRYINSERTED, "GoodEntryInserted"},
+ {UA_STATUSCODE_GOODENTRYREPLACED, "GoodEntryReplaced"},
+ {UA_STATUSCODE_UNCERTAINDATASUBNORMAL, "UncertainDataSubNormal"},
+ {UA_STATUSCODE_GOODNODATA, "GoodNoData"},
+ {UA_STATUSCODE_GOODMOREDATA, "GoodMoreData"},
+ {UA_STATUSCODE_BADAGGREGATELISTMISMATCH, "BadAggregateListMismatch"},
+ {UA_STATUSCODE_BADAGGREGATENOTSUPPORTED, "BadAggregateNotSupported"},
+ {UA_STATUSCODE_BADAGGREGATEINVALIDINPUTS, "BadAggregateInvalidInputs"},
+ {UA_STATUSCODE_BADAGGREGATECONFIGURATIONREJECTED, "BadAggregateConfigurationRejected"},
+ {UA_STATUSCODE_GOODDATAIGNORED, "GoodDataIgnored"},
+ {UA_STATUSCODE_BADREQUESTNOTALLOWED, "BadRequestNotAllowed"},
+ {UA_STATUSCODE_GOODEDITED, "GoodEdited"},
+ {UA_STATUSCODE_GOODPOSTACTIONFAILED, "GoodPostActionFailed"},
+ {UA_STATUSCODE_UNCERTAINDOMINANTVALUECHANGED, "UncertainDominantValueChanged"},
+ {UA_STATUSCODE_GOODDEPENDENTVALUECHANGED, "GoodDependentValueChanged"},
+ {UA_STATUSCODE_BADDOMINANTVALUECHANGED, "BadDominantValueChanged"},
+ {UA_STATUSCODE_UNCERTAINDEPENDENTVALUECHANGED, "UncertainDependentValueChanged"},
+ {UA_STATUSCODE_BADDEPENDENTVALUECHANGED, "BadDependentValueChanged"},
+ {UA_STATUSCODE_GOODCOMMUNICATIONEVENT, "GoodCommunicationEvent"},
+ {UA_STATUSCODE_GOODSHUTDOWNEVENT, "GoodShutdownEvent"},
+ {UA_STATUSCODE_GOODCALLAGAIN, "GoodCallAgain"},
+ {UA_STATUSCODE_GOODNONCRITICALTIMEOUT, "GoodNonCriticalTimeout"},
+ {UA_STATUSCODE_BADINVALIDARGUMENT, "BadInvalidArgument"},
+ {UA_STATUSCODE_BADCONNECTIONREJECTED, "BadConnectionRejected"},
+ {UA_STATUSCODE_BADDISCONNECT, "BadDisconnect"},
+ {UA_STATUSCODE_BADCONNECTIONCLOSED, "BadConnectionClosed"},
+ {UA_STATUSCODE_BADINVALIDSTATE, "BadInvalidState"},
+ {UA_STATUSCODE_BADENDOFSTREAM, "BadEndOfStream"},
+ {UA_STATUSCODE_BADNODATAAVAILABLE, "BadNoDataAvailable"},
+ {UA_STATUSCODE_BADWAITINGFORRESPONSE, "BadWaitingForResponse"},
+ {UA_STATUSCODE_BADOPERATIONABANDONED, "BadOperationAbandoned"},
+ {UA_STATUSCODE_BADEXPECTEDSTREAMTOBLOCK, "BadExpectedStreamToBlock"},
+ {UA_STATUSCODE_BADWOULDBLOCK, "BadWouldBlock"},
+ {UA_STATUSCODE_BADSYNTAXERROR, "BadSyntaxError"},
+ {UA_STATUSCODE_BADMAXCONNECTIONSREACHED, "BadMaxConnectionsReached"},
+ {0xffffffff, "Unknown StatusCode"}
+};
+
+const char * UA_StatusCode_name(UA_StatusCode code) {
+ for (size_t i = 0; i < statusCodeDescriptionsSize; ++i) {
+ if (statusCodeDescriptions[i].code == code)
+ return statusCodeDescriptions[i].name;
+ }
+ return statusCodeDescriptions[statusCodeDescriptionsSize-1].name;
+}
+
+#endif
+
+/*********************************** amalgamated original file "/home/jvoe/open62541/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
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * Copyright 2014, 2017 (c) Julius Pfrommer, Fraunhofer IOSB
+ * Copyright 2014 (c) Florian Palm
+ * Copyright 2017 (c) Stefan Profanter, fortiss GmbH
+ */
+
+
+size_t
+UA_readNumber(u8 *buf, size_t buflen, u32 *number) {
+ UA_assert(buf);
+ UA_assert(number);
+ u32 n = 0;
+ size_t progress = 0;
+ /* read numbers until the end or a non-number character appears */
+ while(progress < buflen) {
+ u8 c = buf[progress];
+ if(c < '0' || c > '9')
+ break;
+ n = (n*10) + (u32)(c-'0');
+ ++progress;
+ }
+ *number = n;
+ return progress;
+}
+
+UA_StatusCode
+UA_parseEndpointUrl(const UA_String *endpointUrl, UA_String *outHostname,
+ u16 *outPort, UA_String *outPath) {
+ /* Url must begin with "opc.tcp://" or opc.udp:// (if pubsub enabled) */
+ if(endpointUrl->length < 11) {
+ return UA_STATUSCODE_BADTCPENDPOINTURLINVALID;
+ } else if (strncmp((char*)endpointUrl->data, "opc.tcp://", 10) != 0) {
+#ifdef UA_ENABLE_PUBSUB
+ if (strncmp((char*)endpointUrl->data, "opc.udp://", 10) != 0) {
+ return UA_STATUSCODE_BADTCPENDPOINTURLINVALID;
+ }
+#else
+ return UA_STATUSCODE_BADTCPENDPOINTURLINVALID;
+#endif
+ }
+
+ /* Where does the hostname end? */
+ size_t curr = 10;
+ if(endpointUrl->data[curr] == '[') {
+ /* IPv6: opc.tcp://[2001:0db8:85a3::8a2e:0370:7334]:1234/path */
+ for(; curr < endpointUrl->length; ++curr) {
+ if(endpointUrl->data[curr] == ']')
+ break;
+ }
+ if(curr == endpointUrl->length)
+ return UA_STATUSCODE_BADTCPENDPOINTURLINVALID;
+ curr++;
+ } else {
+ /* IPv4 or hostname: opc.tcp://something.something:1234/path */
+ for(; curr < endpointUrl->length; ++curr) {
+ if(endpointUrl->data[curr] == ':' || endpointUrl->data[curr] == '/')
+ break;
+ }
+ }
+
+ /* Set the hostname */
+ outHostname->data = &endpointUrl->data[10];
+ outHostname->length = curr - 10;
+ if(curr == endpointUrl->length)
+ return UA_STATUSCODE_GOOD;
+
+ /* Set the port */
+ if(endpointUrl->data[curr] == ':') {
+ if(++curr == endpointUrl->length)
+ return UA_STATUSCODE_BADTCPENDPOINTURLINVALID;
+ u32 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 */
+ curr += progress;
+ if(curr == endpointUrl->length || endpointUrl->data[curr] == '/')
+ *outPort = (u16)largeNum;
+ if(curr == endpointUrl->length)
+ return UA_STATUSCODE_GOOD;
+ }
+
+ /* Set the path */
+ UA_assert(curr < endpointUrl->length);
+ if(endpointUrl->data[curr] != '/')
+ return UA_STATUSCODE_BADTCPENDPOINTURLINVALID;
+ if(++curr == endpointUrl->length)
+ return UA_STATUSCODE_GOOD;
+ outPath->data = &endpointUrl->data[curr];
+ outPath->length = endpointUrl->length - curr;
+
+ /* Remove trailing slash from the path */
+ if(endpointUrl->data[endpointUrl->length - 1] == '/')
+ outPath->length--;
+
+ return UA_STATUSCODE_GOOD;
+}
+
+/*********************************** amalgamated original file "/home/jvoe/open62541/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 (c) Julius Pfrommer, Fraunhofer IOSB
+ * Copyright 2017 (c) Stefan Profanter, fortiss GmbH
+ */
+
+
+/* Only one thread operates on the repeated jobs. This is usually the "main"
+ * thread with the event loop. All other threads introduce changes via a
+ * multi-producer single-consumer (MPSC) queue. The queue is based on a design
+ * by Dmitry Vyukov.
+ * http://www.1024cores.net/home/lock-free-algorithms/queues/intrusive-mpsc-node-based-queue
+ *
+ * The RepeatedCallback structure is used both in the sorted list of callbacks
+ * and in the MPSC changes queue. For the changes queue, we differentiate
+ * between three cases encoded in the callback pointer.
+ *
+ * callback > 0x01: add the new repeated callback to the sorted list
+ * callback == 0x00: remove the callback with the same id
+ * callback == 0x01: change the interval of the existing callback */
+
+#define REMOVE_SENTINEL 0x00
+#define CHANGE_SENTINEL 0x01
+
+struct UA_TimerCallbackEntry {
+ SLIST_ENTRY(UA_TimerCallbackEntry) next; /* Next element in the list */
+ UA_DateTime nextTime; /* The next time when the callbacks
+ * are to be executed */
+ UA_UInt64 interval; /* Interval in 100ns resolution */
+ UA_UInt64 id; /* Id of the repeated callback */
+
+ UA_TimerCallback callback;
+ void *data;
+};
+
+void
+UA_Timer_init(UA_Timer *t) {
+ SLIST_INIT(&t->repeatedCallbacks);
+ t->changes_head = (UA_TimerCallbackEntry*)&t->changes_stub;
+ t->changes_tail = (UA_TimerCallbackEntry*)&t->changes_stub;
+ t->changes_stub = NULL;
+ t->idCounter = 0;
+}
+
+static void
+enqueueChange(UA_Timer *t, UA_TimerCallbackEntry *tc) {
+ tc->next.sle_next = NULL;
+ UA_TimerCallbackEntry *prev = (UA_TimerCallbackEntry*)
+ UA_atomic_xchg((void * volatile *)&t->changes_head, tc);
+ /* Nothing can be dequeued while the producer is blocked here */
+ prev->next.sle_next = tc; /* Once this change is visible in the consumer,
+ * the node is dequeued in the following
+ * iteration */
+}
+
+static UA_TimerCallbackEntry *
+dequeueChange(UA_Timer *t) {
+ UA_TimerCallbackEntry *tail = t->changes_tail;
+ UA_TimerCallbackEntry *next = tail->next.sle_next;
+ if(tail == (UA_TimerCallbackEntry*)&t->changes_stub) {
+ if(!next)
+ return NULL;
+ t->changes_tail = next;
+ tail = next;
+ next = next->next.sle_next;
+ }
+ if(next) {
+ t->changes_tail = next;
+ return tail;
+ }
+ UA_TimerCallbackEntry* head = t->changes_head;
+ if(tail != head)
+ return NULL;
+ enqueueChange(t, (UA_TimerCallbackEntry*)&t->changes_stub);
+ next = tail->next.sle_next;
+ if(next) {
+ t->changes_tail = next;
+ return tail;
+ }
+ return NULL;
+}
+
+/* Adding repeated callbacks: Add an entry with the "nextTime" timestamp in the
+ * future. This will be picked up in the next iteration and inserted at the
+ * correct place. So that the next execution takes place ät "nextTime". */
+UA_StatusCode
+UA_Timer_addRepeatedCallback(UA_Timer *t, UA_TimerCallback callback,
+ void *data, UA_UInt32 interval,
+ UA_UInt64 *callbackId) {
+ /* A callback method needs to be present */
+ if(!callback)
+ return UA_STATUSCODE_BADINTERNALERROR;
+
+ /* The interval needs to be at least 5ms */
+ if(interval < 5)
+ return UA_STATUSCODE_BADINTERNALERROR;
+
+ /* Allocate the repeated callback structure */
+ UA_TimerCallbackEntry *tc =
+ (UA_TimerCallbackEntry*)UA_malloc(sizeof(UA_TimerCallbackEntry));
+ if(!tc)
+ return UA_STATUSCODE_BADOUTOFMEMORY;
+
+ /* Set the repeated callback */
+ tc->interval = (UA_UInt64)interval * UA_DATETIME_MSEC;
+ tc->id = ++t->idCounter;
+ tc->callback = callback;
+ tc->data = data;
+ tc->nextTime = UA_DateTime_nowMonotonic() + (UA_DateTime)tc->interval;
+
+ /* Set the output identifier */
+ if(callbackId)
+ *callbackId = tc->id;
+
+ /* Enqueue the changes in the MPSC queue */
+ enqueueChange(t, tc);
+ return UA_STATUSCODE_GOOD;
+}
+
+static void
+addTimerCallbackEntry(UA_Timer *t, UA_TimerCallbackEntry * UA_RESTRICT tc) {
+ /* Find the last entry before this callback */
+ UA_TimerCallbackEntry *tmpTc, *afterTc = NULL;
+ SLIST_FOREACH(tmpTc, &t->repeatedCallbacks, next) {
+ if(tmpTc->nextTime >= tc->nextTime)
+ break;
+
+ /* The goal is to have many repeated callbacks with the same repetition
+ * interval in a "block" in order to reduce linear search for re-entry
+ * to the sorted list after processing. Allow the first execution to lie
+ * between "nextTime - 1s" and "nextTime" if this adjustment groups
+ * callbacks with the same repetition interval.
+ * Callbacks of a block are added in reversed order. This design allows
+ * the monitored items of a subscription (if created in a sequence with the
+ * same publish/sample interval) to be executed before the subscription
+ * publish the notifications */
+ if(tmpTc->interval == tc->interval &&
+ tmpTc->nextTime > (tc->nextTime - UA_DATETIME_SEC)) {
+ tc->nextTime = tmpTc->nextTime;
+ break;
+ }
+
+ /* tc is neither in the same interval nor supposed to be executed sooner
+ * than tmpTc. Update afterTc to push tc further back in the timer list. */
+ afterTc = tmpTc;
+ }
+
+ /* Add the repeated callback */
+ if(afterTc)
+ SLIST_INSERT_AFTER(afterTc, tc, next);
+ else
+ SLIST_INSERT_HEAD(&t->repeatedCallbacks, tc, next);
+}
+
+UA_StatusCode
+UA_Timer_changeRepeatedCallbackInterval(UA_Timer *t, UA_UInt64 callbackId,
+ UA_UInt32 interval) {
+ /* The interval needs to be at least 5ms */
+ if(interval < 5)
+ return UA_STATUSCODE_BADINTERNALERROR;
+
+ /* Allocate the repeated callback structure */
+ UA_TimerCallbackEntry *tc =
+ (UA_TimerCallbackEntry*)UA_malloc(sizeof(UA_TimerCallbackEntry));
+ if(!tc)
+ return UA_STATUSCODE_BADOUTOFMEMORY;
+
+ /* Set the repeated callback */
+ tc->interval = (UA_UInt64)interval * UA_DATETIME_MSEC;
+ tc->id = callbackId;
+ tc->nextTime = UA_DateTime_nowMonotonic() + (UA_DateTime)tc->interval;
+ tc->callback = (UA_TimerCallback)CHANGE_SENTINEL;
+
+ /* Enqueue the changes in the MPSC queue */
+ enqueueChange(t, tc);
+ return UA_STATUSCODE_GOOD;
+}
+
+static void
+changeTimerCallbackEntryInterval(UA_Timer *t, UA_UInt64 callbackId,
+ UA_UInt64 interval, UA_DateTime nextTime) {
+ /* Remove from the sorted list */
+ UA_TimerCallbackEntry *tc, *prev = NULL;
+ SLIST_FOREACH(tc, &t->repeatedCallbacks, next) {
+ if(callbackId == tc->id) {
+ if(prev)
+ SLIST_REMOVE_AFTER(prev, next);
+ else
+ SLIST_REMOVE_HEAD(&t->repeatedCallbacks, next);
+ break;
+ }
+ prev = tc;
+ }
+ if(!tc)
+ return;
+
+ /* Adjust settings */
+ tc->interval = interval;
+ tc->nextTime = nextTime;
+
+ /* Reinsert at the new position */
+ addTimerCallbackEntry(t, tc);
+}
+
+/* Removing a repeated callback: Add an entry with the "nextTime" timestamp set
+ * to UA_INT64_MAX. The next iteration picks this up and removes the repated
+ * callback from the linked list. */
+UA_StatusCode
+UA_Timer_removeRepeatedCallback(UA_Timer *t, UA_UInt64 callbackId) {
+ /* Allocate the repeated callback structure */
+ UA_TimerCallbackEntry *tc =
+ (UA_TimerCallbackEntry*)UA_malloc(sizeof(UA_TimerCallbackEntry));
+ if(!tc)
+ return UA_STATUSCODE_BADOUTOFMEMORY;
+
+ /* Set the repeated callback with the sentinel nextTime */
+ tc->id = callbackId;
+ tc->callback = (UA_TimerCallback)REMOVE_SENTINEL;
+
+ /* Enqueue the changes in the MPSC queue */
+ enqueueChange(t, tc);
+ return UA_STATUSCODE_GOOD;
+}
+
+static void
+removeRepeatedCallback(UA_Timer *t, UA_UInt64 callbackId) {
+ UA_TimerCallbackEntry *tc, *prev = NULL;
+ SLIST_FOREACH(tc, &t->repeatedCallbacks, next) {
+ if(callbackId == tc->id) {
+ if(prev)
+ SLIST_REMOVE_AFTER(prev, next);
+ else
+ SLIST_REMOVE_HEAD(&t->repeatedCallbacks, next);
+ UA_free(tc);
+ break;
+ }
+ prev = tc;
+ }
+}
+
+/* Process the changes that were added to the MPSC queue (by other threads) */
+static void
+processChanges(UA_Timer *t) {
+ UA_TimerCallbackEntry *change;
+ while((change = dequeueChange(t))) {
+ switch((uintptr_t)change->callback) {
+ case REMOVE_SENTINEL:
+ removeRepeatedCallback(t, change->id);
+ UA_free(change);
+ break;
+ case CHANGE_SENTINEL:
+ changeTimerCallbackEntryInterval(t, change->id, change->interval,
+ change->nextTime);
+ UA_free(change);
+ break;
+ default:
+ addTimerCallbackEntry(t, change);
+ }
+ }
+}
+
+UA_DateTime
+UA_Timer_process(UA_Timer *t, UA_DateTime nowMonotonic,
+ UA_TimerDispatchCallback dispatchCallback,
+ void *application) {
+ /* Insert and remove callbacks */
+ processChanges(t);
+
+ /* Find the last callback to be executed now */
+ UA_TimerCallbackEntry *firstAfter, *lastNow = NULL;
+ SLIST_FOREACH(firstAfter, &t->repeatedCallbacks, next) {
+ if(firstAfter->nextTime > nowMonotonic)
+ break;
+ lastNow = firstAfter;
+ }
+
+ /* Nothing to do */
+ if(!lastNow) {
+ if(firstAfter)
+ return firstAfter->nextTime;
+ return UA_INT64_MAX;
+ }
+
+ /* Put the callbacks that are executed now in a separate list */
+ UA_TimerCallbackList executedNowList;
+ executedNowList.slh_first = SLIST_FIRST(&t->repeatedCallbacks);
+ lastNow->next.sle_next = NULL;
+
+ /* Fake entry to represent the first element in the newly-sorted list */
+ UA_TimerCallbackEntry tmp_first;
+ tmp_first.nextTime = nowMonotonic - 1; /* never matches for last_dispatched */
+ tmp_first.next.sle_next = firstAfter;
+ UA_TimerCallbackEntry *last_dispatched = &tmp_first;
+
+ /* Iterate over the list of callbacks to process now */
+ UA_TimerCallbackEntry *tc;
+ while((tc = SLIST_FIRST(&executedNowList))) {
+ /* Remove from the list */
+ SLIST_REMOVE_HEAD(&executedNowList, next);
+
+ /* Dispatch/process callback */
+ dispatchCallback(application, tc->callback, tc->data);
+
+ /* Set the time for the next execution. Prevent an infinite loop by
+ * forcing the next processing into the next iteration. */
+ tc->nextTime += (UA_Int64)tc->interval;
+ if(tc->nextTime < nowMonotonic)
+ tc->nextTime = nowMonotonic + 1;
+
+ /* Find the new position for tc to keep the list sorted */
+ UA_TimerCallbackEntry *prev_tc;
+ if(last_dispatched->nextTime == tc->nextTime) {
+ /* We try to "batch" repeatedCallbacks with the same interval. This
+ * saves a linear search when the last dispatched entry has the same
+ * nextTime timestamp as this entry. */
+ UA_assert(last_dispatched != &tmp_first);
+ prev_tc = last_dispatched;
+ } else {
+ /* Find the position for the next execution by a linear search
+ * starting at last_dispatched or the first element */
+ if(last_dispatched->nextTime < tc->nextTime)
+ prev_tc = last_dispatched;
+ else
+ prev_tc = &tmp_first;
+
+ while(true) {
+ UA_TimerCallbackEntry *n = SLIST_NEXT(prev_tc, next);
+ if(!n || n->nextTime >= tc->nextTime)
+ break;
+ prev_tc = n;
+ }
+ }
+
+ /* Update last_dispatched to make sure batched callbacks are added in the
+ * same sequence as before they were executed and to save some iterations
+ * of the linear search for callbacks to be added further back in the list. */
+ last_dispatched = tc;
+
+ /* Add entry to the new position in the sorted list */
+ SLIST_INSERT_AFTER(prev_tc, tc, next);
+ }
+
+ /* Set the entry-point for the newly sorted list */
+ t->repeatedCallbacks.slh_first = tmp_first.next.sle_next;
+
+ /* Re-repeat processAddRemoved since one of the callbacks might have removed
+ * or added a callback. So we return a correct timeout. */
+ processChanges(t);
+
+ /* Return timestamp of next repetition */
+ tc = SLIST_FIRST(&t->repeatedCallbacks);
+ if(!tc)
+ return UA_INT64_MAX; /* Main-loop has a max timeout / will continue earlier */
+ return tc->nextTime;
+}
+
+void
+UA_Timer_deleteMembers(UA_Timer *t) {
+ /* Process changes to empty the MPSC queue */
+ processChanges(t);
+
+ /* Remove repeated callbacks */
+ UA_TimerCallbackEntry *current;
+ while((current = SLIST_FIRST(&t->repeatedCallbacks))) {
+ SLIST_REMOVE_HEAD(&t->repeatedCallbacks, next);
+ UA_free(current);
+ }
+}
+
+/*********************************** amalgamated original file "/home/jvoe/open62541/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
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * Copyright 2014-2017 (c) Julius Pfrommer, Fraunhofer IOSB
+ * Copyright 2014, 2016-2017 (c) Florian Palm
+ * Copyright 2015-2016 (c) Sten Grüner
+ * Copyright 2015 (c) Oleksiy Vasylyev
+ * Copyright 2016-2017 (c) Stefan Profanter, fortiss GmbH
+ * Copyright 2017 (c) Mark Giraud, Fraunhofer IOSB
+ */
+
+
+void UA_Connection_deleteMembers(UA_Connection *connection) {
+ UA_ByteString_deleteMembers(&connection->incompleteMessage);
+}
+
+/* Hides somme errors before sending them to a client according to the
+ * standard. */
+static void
+hideErrors(UA_TcpErrorMessage *const error) {
+ switch(error->error) {
+ case UA_STATUSCODE_BADCERTIFICATEUNTRUSTED:
+ error->error = UA_STATUSCODE_BADSECURITYCHECKSFAILED;
+ error->reason = UA_STRING_NULL;
+ break;
+ // TODO: Check if these are all cases that need to be covered.
+ default:
+ break;
+ }
+}
+
+void
+UA_Connection_sendError(UA_Connection *connection, UA_TcpErrorMessage *error) {
+ hideErrors(error);
+
+ UA_TcpMessageHeader header;
+ header.messageTypeAndChunkType = UA_MESSAGETYPE_ERR + UA_CHUNKTYPE_FINAL;
+ // Header + ErrorMessage (error + reasonLength_field + length)
+ header.messageSize = 8 + (4 + 4 + (UA_UInt32)error->reason.length);
+
+ /* Get the send buffer from the network layer */
+ UA_ByteString msg = UA_BYTESTRING_NULL;
+ UA_StatusCode retval = connection->getSendBuffer(connection, header.messageSize, &msg);
+ if(retval != UA_STATUSCODE_GOOD)
+ return;
+
+ /* 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);
+ msg.length = header.messageSize;
+ connection->send(connection, &msg);
+}
+
+static UA_StatusCode
+prependIncompleteChunk(UA_Connection *connection, UA_ByteString *message) {
+ /* Allocate the new message buffer */
+ size_t length = connection->incompleteMessage.length + message->length;
+ UA_Byte *data = (UA_Byte*)UA_realloc(connection->incompleteMessage.data, length);
+ if(!data) {
+ UA_ByteString_deleteMembers(&connection->incompleteMessage);
+ return UA_STATUSCODE_BADOUTOFMEMORY;
+ }
+
+ /* Copy / release the current message buffer */
+ memcpy(&data[connection->incompleteMessage.length], message->data, message->length);
+ message->length = length;
+ message->data = data;
+ connection->incompleteMessage = UA_BYTESTRING_NULL;
+ return UA_STATUSCODE_GOOD;
+}
+
+static UA_StatusCode
+bufferIncompleteChunk(UA_Connection *connection, const UA_Byte *pos, const UA_Byte *end) {
+ size_t length = (uintptr_t)end - (uintptr_t)pos;
+ UA_StatusCode retval = UA_ByteString_allocBuffer(&connection->incompleteMessage, length);
+ if(retval != UA_STATUSCODE_GOOD)
+ return retval;
+ memcpy(connection->incompleteMessage.data, pos, length);
+ return UA_STATUSCODE_GOOD;
+}
+
+static UA_StatusCode
+processChunk(UA_Connection *connection, void *application,
+ UA_Connection_processChunk processCallback,
+ const UA_Byte **posp, const UA_Byte *end, UA_Boolean *done) {
+ const UA_Byte *pos = *posp;
+ size_t length = (uintptr_t)end - (uintptr_t)pos;
+
+ /* At least 8 byte needed for the header. Wait for the next chunk. */
+ if(length < 8) {
+ bufferIncompleteChunk(connection, pos, end);
+ *done = true;
+ return UA_STATUSCODE_GOOD;
+ }
+
+ /* Check the message type */
+ UA_MessageType msgtype = (UA_MessageType)((UA_UInt32)pos[0] + ((UA_UInt32)pos[1] << 8) +
+ ((UA_UInt32)pos[2] << 16));
+ if(msgtype != UA_MESSAGETYPE_MSG && msgtype != UA_MESSAGETYPE_ERR &&
+ msgtype != UA_MESSAGETYPE_OPN && msgtype != UA_MESSAGETYPE_HEL &&
+ msgtype != UA_MESSAGETYPE_ACK && msgtype != UA_MESSAGETYPE_CLO) {
+ /* The message type is not recognized */
+ return UA_STATUSCODE_BADTCPMESSAGETYPEINVALID;
+ }
+
+ UA_Byte isFinal = pos[3];
+ if(isFinal != 'C' && isFinal != 'F' && isFinal != 'A') {
+ /* The message type is not recognized */
+ return UA_STATUSCODE_BADTCPMESSAGETYPEINVALID;
+ }
+
+ UA_UInt32 chunk_length = 0;
+ UA_ByteString temp = { 8, (UA_Byte*)(uintptr_t)pos }; /* At least 8 byte left */
+ size_t temp_offset = 4;
+ /* Decoding the UInt32 cannot fail */
+ UA_UInt32_decodeBinary(&temp, &temp_offset, &chunk_length);
+
+ /* The message size is not allowed */
+ if(chunk_length < 16 || chunk_length > connection->localConf.recvBufferSize)
+ return UA_STATUSCODE_BADTCPMESSAGETOOLARGE;
+
+ /* Wait for the next packet to process the complete chunk */
+ if(chunk_length > length) {
+ bufferIncompleteChunk(connection, pos, end);
+ *done = true;
+ return UA_STATUSCODE_GOOD;
+ }
+
+ /* Set pendingMessage if there is a message after this message */
+ if(length > chunk_length)
+ connection->pendingMessage = true;
+
+ /* Process the chunk; forward the position pointer */
+ temp.length = chunk_length;
+ *posp += chunk_length;
+ *done = false;
+ return processCallback(application, connection, &temp);
+}
+
+UA_StatusCode
+UA_Connection_processChunks(UA_Connection *connection, void *application,
+ UA_Connection_processChunk processCallback,
+ const UA_ByteString *packet) {
+ /* If we have stored an incomplete chunk, prefix to the received message.
+ * After this block, connection->incompleteMessage is always empty. The
+ * message and the buffer is released if allocating the memory fails. */
+ UA_Boolean realloced = false;
+ UA_ByteString message = *packet;
+ UA_StatusCode retval;
+ if(connection->incompleteMessage.length > 0) {
+ retval = prependIncompleteChunk(connection, &message);
+ if(retval != UA_STATUSCODE_GOOD)
+ return retval;
+ realloced = true;
+ }
+
+ /* Loop over the received chunks. pos is increased with each chunk. */
+ const UA_Byte *pos = message.data;
+ const UA_Byte *end = &message.data[message.length];
+ UA_Boolean done = true;
+ do {
+ retval = processChunk(connection, application, processCallback,
+ &pos, end, &done);
+ connection->pendingMessage = false;
+ } while(!done && retval == UA_STATUSCODE_GOOD);
+
+ if(realloced)
+ UA_ByteString_deleteMembers(&message);
+ return retval;
+}
+
+/* In order to know whether a chunk was processed, we insert an indirection into
+ * the callback. */
+struct completeChunkTrampolineData {
+ UA_Boolean called;
+ void *application;
+ UA_Connection_processChunk processCallback;
+};
+
+static UA_StatusCode
+completeChunkTrampoline(void *application, UA_Connection *connection,
+ UA_ByteString *chunk) {
+ struct completeChunkTrampolineData *data =
+ (struct completeChunkTrampolineData*)application;
+ data->called = true;
+ return data->processCallback(data->application, connection, chunk);
+}
+
+UA_StatusCode
+UA_Connection_receiveChunksBlocking(UA_Connection *connection, void *application,
+ UA_Connection_processChunk processCallback,
+ UA_UInt32 timeout) {
+ UA_DateTime now = UA_DateTime_nowMonotonic();
+ UA_DateTime maxDate = now + (timeout * UA_DATETIME_MSEC);
+
+ struct completeChunkTrampolineData data;
+ data.called = false;
+ data.application = application;
+ data.processCallback = processCallback;
+
+ UA_StatusCode retval = UA_STATUSCODE_GOOD;
+ while(true) {
+ /* Listen for messages to arrive */
+ UA_ByteString packet = UA_BYTESTRING_NULL;
+ retval = connection->recv(connection, &packet, timeout);
+ if(retval != UA_STATUSCODE_GOOD)
+ break;
+
+ /* Try to process one complete chunk */
+ retval = UA_Connection_processChunks(connection, &data,
+ completeChunkTrampoline, &packet);
+ connection->releaseRecvBuffer(connection, &packet);
+ if(data.called)
+ break;
+
+ /* We received a message. But the chunk is incomplete. Compute the
+ * remaining timeout. */
+ now = UA_DateTime_nowMonotonic();
+
+ /* >= avoid timeout to be set to 0 */
+ if(now >= maxDate)
+ return UA_STATUSCODE_GOODNONCRITICALTIMEOUT;
+
+ /* round always to upper value to avoid timeout to be set to 0
+ * if(maxDate - now) < (UA_DATETIME_MSEC/2) */
+ timeout = (UA_UInt32)(((maxDate - now) + (UA_DATETIME_MSEC - 1)) / UA_DATETIME_MSEC);
+ }
+ return retval;
+}
+
+void UA_Connection_detachSecureChannel(UA_Connection *connection) {
+ UA_SecureChannel *channel = connection->channel;
+ if(channel)
+ /* only replace when the channel points to this connection */
+ UA_atomic_cmpxchg((void**)&channel->connection, connection, NULL);
+ UA_atomic_xchg((void**)&connection->channel, NULL);
+}
+
+// TODO: Return an error code
+void
+UA_Connection_attachSecureChannel(UA_Connection *connection, UA_SecureChannel *channel) {
+ if(UA_atomic_cmpxchg((void**)&channel->connection, NULL, connection) == NULL)
+ UA_atomic_xchg((void**)&connection->channel, (void*)channel);
+}
+
+/*********************************** amalgamated original file "/home/jvoe/open62541/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
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * Copyright 2014-2018 (c) Julius Pfrommer, Fraunhofer IOSB
+ * Copyright 2014, 2016-2017 (c) Florian Palm
+ * Copyright 2015-2016 (c) Sten Grüner
+ * Copyright 2015 (c) Oleksiy Vasylyev
+ * Copyright 2016 (c) TorbenD
+ * Copyright 2017 (c) Stefan Profanter, fortiss GmbH
+ * Copyright 2017-2018 (c) Mark Giraud, Fraunhofer IOSB
+ */
+
+
+#define UA_BITMASK_MESSAGETYPE 0x00ffffff
+#define UA_BITMASK_CHUNKTYPE 0xff000000
+#define UA_ASYMMETRIC_ALG_SECURITY_HEADER_FIXED_LENGTH 12
+#define UA_SYMMETRIC_ALG_SECURITY_HEADER_LENGTH 4
+#define UA_SEQUENCE_HEADER_LENGTH 8
+#define UA_SECUREMH_AND_SYMALGH_LENGTH \
+ (UA_SECURE_CONVERSATION_MESSAGE_HEADER_LENGTH + \
+ UA_SYMMETRIC_ALG_SECURITY_HEADER_LENGTH)
+
+const UA_ByteString
+ UA_SECURITY_POLICY_NONE_URI = {47, (UA_Byte *)"http://opcfoundation.org/UA/SecurityPolicy#None"};
+
+#ifdef UA_ENABLE_UNIT_TEST_FAILURE_HOOKS
+UA_StatusCode decrypt_verifySignatureFailure;
+UA_StatusCode sendAsym_sendFailure;
+UA_StatusCode processSym_seqNumberFailure;
+#endif
+
+UA_StatusCode
+UA_SecureChannel_init(UA_SecureChannel *channel,
+ const UA_SecurityPolicy *securityPolicy,
+ const UA_ByteString *remoteCertificate) {
+ if(channel == NULL || securityPolicy == NULL || remoteCertificate == NULL)
+ return UA_STATUSCODE_BADINTERNALERROR;
+
+ /* Linked lists are also initialized by zeroing out */
+ memset(channel, 0, sizeof(UA_SecureChannel));
+ channel->state = UA_SECURECHANNELSTATE_FRESH;
+ channel->securityPolicy = securityPolicy;
+
+ UA_StatusCode retval;
+ if(channel->securityPolicy->certificateVerification != NULL) {
+ retval = channel->securityPolicy->certificateVerification->
+ verifyCertificate(channel->securityPolicy->certificateVerification->context, remoteCertificate);
+
+ if(retval != UA_STATUSCODE_GOOD)
+ return retval;
+ } else {
+ UA_LOG_WARNING(channel->securityPolicy->logger, UA_LOGCATEGORY_SECURITYPOLICY, "No PKI plugin set. "
+ "Accepting all certificates");
+ }
+
+ retval = securityPolicy->channelModule.
+ newContext(securityPolicy, remoteCertificate, &channel->channelContext);
+ if(retval != UA_STATUSCODE_GOOD)
+ 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.
+ makeCertificateThumbprint(securityPolicy, &channel->remoteCertificate,
+ &remoteCertificateThumbprint);
+
+ return retval;
+}
+
+void
+UA_SecureChannel_deleteMembersCleanup(UA_SecureChannel *channel) {
+ /* Delete members */
+ UA_ByteString_deleteMembers(&channel->remoteCertificate);
+ UA_ByteString_deleteMembers(&channel->localNonce);
+ UA_ByteString_deleteMembers(&channel->remoteNonce);
+ UA_ChannelSecurityToken_deleteMembers(&channel->securityToken);
+ UA_ChannelSecurityToken_deleteMembers(&channel->nextSecurityToken);
+
+ /* Delete the channel context for the security policy */
+ if(channel->securityPolicy)
+ channel->securityPolicy->channelModule.deleteContext(channel->channelContext);
+
+ /* Detach from the connection and close the connection */
+ if(channel->connection) {
+ if(channel->connection->state != UA_CONNECTION_CLOSED)
+ channel->connection->close(channel->connection);
+ UA_Connection_detachSecureChannel(channel->connection);
+ }
+
+ /* Remove session pointers (not the sessions) and NULL the pointers back to
+ * the SecureChannel in the Session */
+ UA_SessionHeader *sh, *temp;
+ LIST_FOREACH_SAFE(sh, &channel->sessions, pointers, temp) {
+ sh->channel = NULL;
+ LIST_REMOVE(sh, pointers);
+ }
+
+ /* Remove the buffered chunks */
+ struct MessageEntry *me, *temp_me;
+ LIST_FOREACH_SAFE(me, &channel->chunks, pointers, temp_me) {
+ struct ChunkPayload *cp, *temp_cp;
+ SIMPLEQ_FOREACH_SAFE(cp, &me->chunkPayload, pointers, temp_cp) {
+ UA_ByteString_deleteMembers(&cp->bytes);
+ UA_free(cp);
+ }
+ LIST_REMOVE(me, pointers);
+ UA_free(me);
+ }
+}
+
+UA_StatusCode
+UA_SecureChannel_generateLocalNonce(UA_SecureChannel *channel) {
+ if(!channel->securityPolicy)
+ return UA_STATUSCODE_BADINTERNALERROR;
+
+ /* Is the length of the previous nonce correct? */
+ size_t nonceLength = channel->securityPolicy->symmetricModule.secureChannelNonceLength;
+ if(channel->localNonce.length != nonceLength) {
+ UA_ByteString_deleteMembers(&channel->localNonce);
+ UA_StatusCode retval = UA_ByteString_allocBuffer(&channel->localNonce, nonceLength);
+ if(retval != UA_STATUSCODE_GOOD)
+ return retval;
+ }
+
+ return channel->securityPolicy->symmetricModule.
+ generateNonce(channel->securityPolicy, &channel->localNonce);
+}
+
+static UA_StatusCode
+UA_SecureChannel_generateLocalKeys(const UA_SecureChannel *const channel,
+ const UA_SecurityPolicy *const securityPolicy) {
+ const UA_SecurityPolicyChannelModule *channelModule = &securityPolicy->channelModule;
+ const UA_SecurityPolicySymmetricModule *symmetricModule = &securityPolicy->symmetricModule;
+ const UA_SecurityPolicyCryptoModule *const cryptoModule = &securityPolicy->symmetricModule.cryptoModule;
+ /* Symmetric key length */
+ size_t encryptionKeyLength =
+ cryptoModule->encryptionAlgorithm.getLocalKeyLength(securityPolicy, channel->channelContext);
+ size_t encryptionBlockSize =
+ cryptoModule->encryptionAlgorithm.getLocalBlockSize(securityPolicy, channel->channelContext);
+ size_t signingKeyLength =
+ cryptoModule->signatureAlgorithm.getLocalKeyLength(securityPolicy, channel->channelContext);
+ const size_t bufSize = encryptionBlockSize + signingKeyLength + encryptionKeyLength;
+ UA_STACKARRAY(UA_Byte, bufBytes, bufSize);
+ UA_ByteString buffer = {bufSize, bufBytes};
+
+ /* Local keys */
+ UA_StatusCode retval = symmetricModule->generateKey(securityPolicy, &channel->remoteNonce,
+ &channel->localNonce, &buffer);
+ if(retval != UA_STATUSCODE_GOOD)
+ return retval;
+ const UA_ByteString localSigningKey = {signingKeyLength, buffer.data};
+ const UA_ByteString localEncryptingKey = {encryptionKeyLength,
+ buffer.data + signingKeyLength};
+ const UA_ByteString localIv = {encryptionBlockSize,
+ buffer.data + signingKeyLength +
+ encryptionKeyLength};
+ retval = channelModule->setLocalSymSigningKey(channel->channelContext, &localSigningKey);
+ retval |= channelModule->setLocalSymEncryptingKey(channel->channelContext, &localEncryptingKey);
+ retval |= channelModule->setLocalSymIv(channel->channelContext, &localIv);
+ return retval;
+}
+
+static UA_StatusCode
+UA_SecureChannel_generateRemoteKeys(const UA_SecureChannel *const channel,
+ const UA_SecurityPolicy *const securityPolicy) {
+ const UA_SecurityPolicyChannelModule *channelModule = &securityPolicy->channelModule;
+ const UA_SecurityPolicySymmetricModule *symmetricModule = &securityPolicy->symmetricModule;
+ const UA_SecurityPolicyCryptoModule *const cryptoModule = &securityPolicy->symmetricModule.cryptoModule;
+ /* Symmetric key length */
+ size_t encryptionKeyLength =
+ cryptoModule->encryptionAlgorithm.getRemoteKeyLength(securityPolicy, channel->channelContext);
+ size_t encryptionBlockSize =
+ cryptoModule->encryptionAlgorithm.getRemoteBlockSize(securityPolicy, channel->channelContext);
+ size_t signingKeyLength =
+ cryptoModule->signatureAlgorithm.getRemoteKeyLength(securityPolicy, channel->channelContext);
+ const size_t bufSize = encryptionBlockSize + signingKeyLength + encryptionKeyLength;
+ UA_STACKARRAY(UA_Byte, bufBytes, bufSize);
+ UA_ByteString buffer = {bufSize, bufBytes};
+
+ /* Remote keys */
+ UA_StatusCode retval = symmetricModule->generateKey(securityPolicy, &channel->localNonce,
+ &channel->remoteNonce, &buffer);
+ if(retval != UA_STATUSCODE_GOOD)
+ return retval;
+ const UA_ByteString remoteSigningKey = {signingKeyLength, buffer.data};
+ const UA_ByteString remoteEncryptingKey = {encryptionKeyLength,
+ buffer.data + signingKeyLength};
+ const UA_ByteString remoteIv = {encryptionBlockSize,
+ buffer.data + signingKeyLength +
+ encryptionKeyLength};
+ retval = channelModule->setRemoteSymSigningKey(channel->channelContext, &remoteSigningKey);
+ retval |= channelModule->setRemoteSymEncryptingKey(channel->channelContext, &remoteEncryptingKey);
+ retval |= channelModule->setRemoteSymIv(channel->channelContext, &remoteIv);
+ if(retval != UA_STATUSCODE_GOOD)
+ return retval;
+
+ return retval;
+}
+
+UA_StatusCode
+UA_SecureChannel_generateNewKeys(UA_SecureChannel *channel) {
+ UA_StatusCode retval = UA_SecureChannel_generateLocalKeys(channel, channel->securityPolicy);
+ if(retval != UA_STATUSCODE_GOOD)
+ return retval;
+
+ retval = UA_SecureChannel_generateRemoteKeys(channel, channel->securityPolicy);
+ if(retval != UA_STATUSCODE_GOOD)
+ return retval;
+
+ return retval;
+}
+
+UA_SessionHeader *
+UA_SecureChannel_getSession(UA_SecureChannel *channel,
+ const UA_NodeId *authenticationToken) {
+ struct UA_SessionHeader *sh;
+ LIST_FOREACH(sh, &channel->sessions, pointers) {
+ if(UA_NodeId_equal(&sh->authenticationToken, authenticationToken))
+ break;
+ }
+ return sh;
+}
+
+UA_StatusCode
+UA_SecureChannel_revolveTokens(UA_SecureChannel *channel) {
+ if(channel->nextSecurityToken.tokenId == 0) // no security token issued
+ return UA_STATUSCODE_BADSECURECHANNELTOKENUNKNOWN;
+
+
+ //FIXME: not thread-safe ???? Why is this not thread safe?
+ UA_ChannelSecurityToken_deleteMembers(&channel->previousSecurityToken);
+ UA_ChannelSecurityToken_copy(&channel->securityToken, &channel->previousSecurityToken);
+
+ UA_ChannelSecurityToken_deleteMembers(&channel->securityToken);
+ UA_ChannelSecurityToken_copy(&channel->nextSecurityToken, &channel->securityToken);
+
+ UA_ChannelSecurityToken_deleteMembers(&channel->nextSecurityToken);
+ UA_ChannelSecurityToken_init(&channel->nextSecurityToken);
+ return UA_SecureChannel_generateNewKeys(channel);
+}
+/***************************/
+/* Send Asymmetric Message */
+/***************************/
+
+static UA_UInt16
+calculatePaddingAsym(const UA_SecurityPolicy *securityPolicy, const void *channelContext,
+ size_t bytesToWrite, UA_Byte *paddingSize, UA_Byte *extraPaddingSize) {
+ size_t plainTextBlockSize = securityPolicy->asymmetricModule.cryptoModule.encryptionAlgorithm.
+ getRemotePlainTextBlockSize(securityPolicy, channelContext);
+ size_t signatureSize = securityPolicy->asymmetricModule.cryptoModule.signatureAlgorithm.
+ getLocalSignatureSize(securityPolicy, channelContext);
+ size_t paddingBytes = 1;
+ if(securityPolicy->asymmetricModule.cryptoModule.encryptionAlgorithm.
+ getRemoteKeyLength(securityPolicy, channelContext) > 2048)
+ ++paddingBytes;
+ size_t padding = (plainTextBlockSize - ((bytesToWrite + signatureSize + paddingBytes) %
+ plainTextBlockSize));
+ *paddingSize = (UA_Byte)(padding & 0xff);
+ *extraPaddingSize = (UA_Byte)(padding >> 8);
+ return (UA_UInt16)padding;
+}
+
+static size_t
+calculateAsymAlgSecurityHeaderLength(const UA_SecureChannel *channel) {
+ size_t asymHeaderLength = UA_ASYMMETRIC_ALG_SECURITY_HEADER_FIXED_LENGTH +
+ channel->securityPolicy->policyUri.length;
+ if(channel->securityMode == UA_MESSAGESECURITYMODE_SIGN ||
+ channel->securityMode == UA_MESSAGESECURITYMODE_SIGNANDENCRYPT) {
+ /* OPN is always encrypted even if mode sign only */
+ asymHeaderLength += 20; /* Thumbprints are always 20 byte long */
+ asymHeaderLength += channel->securityPolicy->localCertificate.length;
+ }
+ return asymHeaderLength;
+}
+
+static void
+hideBytesAsym(const UA_SecureChannel *channel, UA_Byte **buf_start, const UA_Byte **buf_end) {
+ const UA_SecurityPolicy *securityPolicy = channel->securityPolicy;
+ *buf_start += UA_SECURE_CONVERSATION_MESSAGE_HEADER_LENGTH + UA_SEQUENCE_HEADER_LENGTH;
+
+ /* Add the SecurityHeaderLength */
+ *buf_start += calculateAsymAlgSecurityHeaderLength(channel);
+ size_t potentialEncryptionMaxSize = (size_t)(*buf_end - *buf_start) + UA_SEQUENCE_HEADER_LENGTH;
+
+ /* Hide bytes for signature and padding */
+ if(channel->securityMode == UA_MESSAGESECURITYMODE_SIGN ||
+ channel->securityMode == UA_MESSAGESECURITYMODE_SIGNANDENCRYPT) {
+ *buf_end -= securityPolicy->asymmetricModule.cryptoModule.signatureAlgorithm.
+ getLocalSignatureSize(securityPolicy, channel->channelContext);
+ *buf_end -= 2; /* padding byte and extraPadding byte */
+
+ /* Add some overhead length due to RSA implementations adding a signature themselves */
+ *buf_end -= UA_SecurityPolicy_getRemoteAsymEncryptionBufferLengthOverhead(securityPolicy,
+ channel->channelContext,
+ potentialEncryptionMaxSize);
+ }
+}
+
+/* Sends an OPN message using asymmetric encryption if defined */
+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;
+
+ const UA_SecurityPolicy *const securityPolicy = channel->securityPolicy;
+ UA_Connection *connection = channel->connection;
+ if(!connection)
+ return UA_STATUSCODE_BADINTERNALERROR;
+
+ /* Allocate the message buffer */
+ UA_ByteString buf = UA_BYTESTRING_NULL;
+ UA_StatusCode retval =
+ connection->getSendBuffer(connection, connection->localConf.sendBufferSize, &buf);
+ if(retval != UA_STATUSCODE_GOOD)
+ return retval;
+
+ /* Restrict buffer to the available space for the payload */
+ UA_Byte *buf_pos = buf.data;
+ const UA_Byte *buf_end = &buf.data[buf.length];
+ 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;
+ }
+
+ /* Compute the length of the asym header */
+ const size_t securityHeaderLength = calculateAsymAlgSecurityHeaderLength(channel);
+
+ /* Pad the message. Also if securitymode is only sign, 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) {
+ 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;
+ UA_Byte paddingSize = 0;
+ UA_Byte extraPaddingSize = 0;
+ UA_UInt16 totalPaddingSize =
+ calculatePaddingAsym(securityPolicy, channel->channelContext,
+ bytesToWrite, &paddingSize, &extraPaddingSize);
+
+ // This is <= because the paddingSize byte also has to be written.
+ for(UA_UInt16 i = 0; i <= totalPaddingSize; ++i) {
+ *buf_pos = paddingSize;
+ ++buf_pos;
+ }
+ if(securityPolicy->asymmetricModule.cryptoModule.encryptionAlgorithm.
+ getRemoteKeyLength(securityPolicy, channel->channelContext) > 2048) {
+ *buf_pos = extraPaddingSize;
+ ++buf_pos;
+ }
+ }
+
+ /* The total message length */
+ size_t pre_sig_length = (uintptr_t)buf_pos - (uintptr_t)buf.data;
+ size_t total_length = pre_sig_length;
+ if(channel->securityMode == UA_MESSAGESECURITYMODE_SIGN ||
+ channel->securityMode == UA_MESSAGESECURITYMODE_SIGNANDENCRYPT)
+ total_length += securityPolicy->asymmetricModule.cryptoModule.signatureAlgorithm.
+ getLocalSignatureSize(securityPolicy, channel->channelContext);
+
+ /* Encode the headers at the beginning of the message */
+ UA_Byte *header_pos = buf.data;
+ size_t dataToEncryptLength =
+ total_length - (UA_SECURE_CONVERSATION_MESSAGE_HEADER_LENGTH + securityHeaderLength);
+ UA_SecureConversationMessageHeader respHeader;
+ respHeader.messageHeader.messageTypeAndChunkType = UA_MESSAGETYPE_OPN + UA_CHUNKTYPE_FINAL;
+ respHeader.messageHeader.messageSize = (UA_UInt32)
+ (total_length + UA_SecurityPolicy_getRemoteAsymEncryptionBufferLengthOverhead(securityPolicy,
+ channel->channelContext,
+ dataToEncryptLength));
+ respHeader.secureChannelId = channel->securityToken.channelId;
+ retval = UA_encodeBinary(&respHeader, &UA_TRANSPORT[UA_TRANSPORT_SECURECONVERSATIONMESSAGEHEADER],
+ &header_pos, &buf_end, NULL, NULL);
+
+ UA_AsymmetricAlgorithmSecurityHeader asymHeader;
+ UA_AsymmetricAlgorithmSecurityHeader_init(&asymHeader);
+ asymHeader.securityPolicyUri = channel->securityPolicy->policyUri;
+ if(channel->securityMode == UA_MESSAGESECURITYMODE_SIGN ||
+ channel->securityMode == UA_MESSAGESECURITYMODE_SIGNANDENCRYPT) {
+ asymHeader.senderCertificate = channel->securityPolicy->localCertificate;
+ asymHeader.receiverCertificateThumbprint.length = 20;
+ asymHeader.receiverCertificateThumbprint.data = channel->remoteCertificateThumbprint;
+ }
+ retval |= UA_encodeBinary(&asymHeader, &UA_TRANSPORT[UA_TRANSPORT_ASYMMETRICALGORITHMSECURITYHEADER],
+ &header_pos, &buf_end, NULL, NULL);
+
+ 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);
+
+ /* Did encoding the header succeed? */
+ if(retval != UA_STATUSCODE_GOOD) {
+ connection->releaseSendBuffer(connection, &buf);
+ return retval;
+ }
+
+ if(channel->securityMode == UA_MESSAGESECURITYMODE_SIGN ||
+ channel->securityMode == UA_MESSAGESECURITYMODE_SIGNANDENCRYPT) {
+ /* Sign message */
+ const UA_ByteString dataToSign = {pre_sig_length, buf.data};
+ size_t sigsize = securityPolicy->asymmetricModule.cryptoModule.signatureAlgorithm.
+ getLocalSignatureSize(securityPolicy, channel->channelContext);
+ UA_ByteString signature = {sigsize, buf.data + pre_sig_length};
+ retval = securityPolicy->asymmetricModule.cryptoModule.signatureAlgorithm.
+ sign(securityPolicy, channel->channelContext, &dataToSign, &signature);
+ if(retval != UA_STATUSCODE_GOOD) {
+ connection->releaseSendBuffer(connection, &buf);
+ 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_ByteString dataToEncrypt = {total_length - unencrypted_length,
+ &buf.data[unencrypted_length]};
+ retval = securityPolicy->asymmetricModule.cryptoModule.encryptionAlgorithm.
+ encrypt(securityPolicy, channel->channelContext, &dataToEncrypt);
+ if(retval != UA_STATUSCODE_GOOD) {
+ connection->releaseSendBuffer(connection, &buf);
+ return retval;
+ }
+ }
+
+ /* Send the message, the buffer is freed in the network layer */
+ buf.length = respHeader.messageHeader.messageSize;
+ retval = connection->send(connection, &buf);
+#ifdef UA_ENABLE_UNIT_TEST_FAILURE_HOOKS
+ retval |= sendAsym_sendFailure
+#endif
+ return retval;
+}
+
+/**************************/
+/* Send Symmetric Message */
+/**************************/
+
+static UA_UInt16
+calculatePaddingSym(const UA_SecurityPolicy *securityPolicy, const void *channelContext,
+ size_t bytesToWrite, UA_Byte *paddingSize, UA_Byte *extraPaddingSize) {
+
+ size_t encryptionBlockSize = securityPolicy->symmetricModule.cryptoModule.encryptionAlgorithm.
+ getLocalBlockSize(securityPolicy, channelContext);
+ size_t signatureSize = securityPolicy->symmetricModule.cryptoModule.signatureAlgorithm.
+ getLocalSignatureSize(securityPolicy, channelContext);
+
+ UA_UInt16 padding = (UA_UInt16)(encryptionBlockSize - ((bytesToWrite + signatureSize + 1) % encryptionBlockSize));
+ *paddingSize = (UA_Byte)padding;
+ *extraPaddingSize = (UA_Byte)(padding >> 8);
+ return padding;
+}
+
+static void
+setBufPos(UA_MessageContext *mc) {
+ const UA_SecureChannel *channel = mc->channel;
+ const UA_SecurityPolicy *securityPolicy = channel->securityPolicy;
+
+ /* 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];
+ mc->buf_end = &mc->messageBuffer.data[mc->messageBuffer.length];
+
+ /* 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 -= securityPolicy->symmetricModule.cryptoModule.signatureAlgorithm.
+ getLocalSignatureSize(securityPolicy, 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 = securityPolicy->symmetricModule.cryptoModule.encryptionAlgorithm.
+ getLocalBlockSize(securityPolicy, channel->channelContext );
+ mc->buf_end -= 1 + ((encryptionBlockSize >> 8) ? 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;
+ }
+}
+
+static UA_StatusCode
+sendSymmetricChunk(UA_MessageContext *mc) {
+ UA_StatusCode res = UA_STATUSCODE_GOOD;
+ UA_SecureChannel *const channel = mc->channel;
+ const UA_SecurityPolicy *securityPolicy = channel->securityPolicy;
+ UA_Connection *const connection = channel->connection;
+ if(!connection)
+ return UA_STATUSCODE_BADINTERNALERROR;
+
+ /* Will this chunk surpass the capacity of the SecureChannel for the message? */
+ UA_Byte *buf_body_start = mc->messageBuffer.data + UA_SECURE_MESSAGE_HEADER_LENGTH;
+ const UA_Byte *buf_body_end = mc->buf_pos;
+ size_t bodyLength = (uintptr_t)buf_body_end - (uintptr_t)buf_body_start;
+ mc->messageSizeSoFar += bodyLength;
+ mc->chunksSoFar++;
+ if(mc->messageSizeSoFar > connection->remoteConf.maxMessageSize &&
+ connection->remoteConf.maxMessageSize != 0)
+ res = UA_STATUSCODE_BADRESPONSETOOLARGE;
+ if(mc->chunksSoFar > connection->remoteConf.maxChunkCount &&
+ connection->remoteConf.maxChunkCount != 0)
+ res = UA_STATUSCODE_BADRESPONSETOOLARGE;
+ if(res != UA_STATUSCODE_GOOD) {
+ connection->releaseSendBuffer(channel->connection, &mc->messageBuffer);
+ return res;
+ }
+
+ /* Pad the message. The bytes for the padding and signature were removed
+ * from buf_end before encoding the payload. So we don't check here. */
+ if(channel->securityMode == UA_MESSAGESECURITYMODE_SIGNANDENCRYPT) {
+ size_t bytesToWrite = bodyLength + UA_SEQUENCE_HEADER_LENGTH;
+ UA_Byte paddingSize = 0;
+ UA_Byte extraPaddingSize = 0;
+ UA_UInt16 totalPaddingSize =
+ calculatePaddingSym(securityPolicy, channel->channelContext,
+ bytesToWrite, &paddingSize, &extraPaddingSize);
+
+ // This is <= because the paddingSize byte also has to be written.
+ for(UA_UInt16 i = 0; i <= totalPaddingSize; ++i) {
+ *mc->buf_pos = paddingSize;
+ ++(mc->buf_pos);
+ }
+ if(extraPaddingSize > 0) {
+ *mc->buf_pos = extraPaddingSize;
+ ++(mc->buf_pos);
+ }
+ }
+
+ /* The total message length */
+ size_t pre_sig_length = (uintptr_t)(mc->buf_pos) - (uintptr_t)mc->messageBuffer.data;
+ size_t 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);
+ /* Space for the padding and the signature have been reserved in setBufPos() */
+ UA_assert(total_length <= connection->localConf.sendBufferSize);
+ mc->messageBuffer.length = total_length; /* For giving the buffer to the network layer */
+
+ /* Encode the chunk headers at the beginning of the buffer */
+ UA_assert(res == UA_STATUSCODE_GOOD);
+ UA_Byte *header_pos = mc->messageBuffer.data;
+ UA_SecureConversationMessageHeader respHeader;
+ respHeader.secureChannelId = channel->securityToken.channelId;
+ respHeader.messageHeader.messageTypeAndChunkType = mc->messageType;
+ respHeader.messageHeader.messageSize = (UA_UInt32)total_length;
+ if(mc->final)
+ respHeader.messageHeader.messageTypeAndChunkType += UA_CHUNKTYPE_FINAL;
+ else
+ respHeader.messageHeader.messageTypeAndChunkType += UA_CHUNKTYPE_INTERMEDIATE;
+ res = UA_encodeBinary(&respHeader, &UA_TRANSPORT[UA_TRANSPORT_SECURECONVERSATIONMESSAGEHEADER],
+ &header_pos, &mc->buf_end, NULL, NULL);
+
+ UA_SymmetricAlgorithmSecurityHeader symSecHeader;
+ symSecHeader.tokenId = channel->securityToken.tokenId;
+ res |= UA_encodeBinary(&symSecHeader.tokenId,
+ &UA_TRANSPORT[UA_TRANSPORT_SYMMETRICALGORITHMSECURITYHEADER],
+ &header_pos, &mc->buf_end, NULL, NULL);
+
+ UA_SequenceHeader seqHeader;
+ seqHeader.requestId = mc->requestId;
+ seqHeader.sequenceNumber = UA_atomic_addUInt32(&channel->sendSequenceNumber, 1);
+ res |= UA_encodeBinary(&seqHeader, &UA_TRANSPORT[UA_TRANSPORT_SEQUENCEHEADER],
+ &header_pos, &mc->buf_end, NULL, NULL);
+
+ /* Sign message */
+ if(channel->securityMode == UA_MESSAGESECURITYMODE_SIGN ||
+ channel->securityMode == UA_MESSAGESECURITYMODE_SIGNANDENCRYPT) {
+ UA_ByteString dataToSign = mc->messageBuffer;
+ dataToSign.length = pre_sig_length;
+ UA_ByteString signature;
+ signature.length = securityPolicy->symmetricModule.cryptoModule.signatureAlgorithm.
+ getLocalSignatureSize(securityPolicy, channel->channelContext);
+ signature.data = mc->buf_pos;
+ res |= securityPolicy->symmetricModule.cryptoModule.signatureAlgorithm.
+ sign(securityPolicy, channel->channelContext, &dataToSign, &signature);
+ }
+
+ /* Encrypt message */
+ if(channel->securityMode == UA_MESSAGESECURITYMODE_SIGNANDENCRYPT) {
+ UA_ByteString dataToEncrypt;
+ dataToEncrypt.data = mc->messageBuffer.data + UA_SECUREMH_AND_SYMALGH_LENGTH;
+ dataToEncrypt.length = total_length - UA_SECUREMH_AND_SYMALGH_LENGTH;
+ res |= securityPolicy->symmetricModule.cryptoModule.encryptionAlgorithm.
+ encrypt(securityPolicy, channel->channelContext, &dataToEncrypt);
+ }
+
+ if(res != UA_STATUSCODE_GOOD) {
+ connection->releaseSendBuffer(channel->connection, &mc->messageBuffer);
+ return res;
+ }
+
+ /* Send the chunk, the buffer is freed in the network layer */
+ return connection->send(channel->connection, &mc->messageBuffer);
+}
+
+/* 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) {
+ /* 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;
+
+ /* Set a new buffer for the next chunk */
+ UA_Connection *connection = mc->channel->connection;
+ retval = connection->getSendBuffer(connection, connection->localConf.sendBufferSize,
+ &mc->messageBuffer);
+ if(retval != UA_STATUSCODE_GOOD)
+ return retval;
+
+ /* Hide bytes for header, padding and signature */
+ setBufPos(mc);
+ *buf_pos = mc->buf_pos;
+ *buf_end = mc->buf_end;
+ return UA_STATUSCODE_GOOD;
+}
+
+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;
+
+ if(messageType != UA_MESSAGETYPE_MSG && messageType != UA_MESSAGETYPE_CLO)
+ return UA_STATUSCODE_BADINTERNALERROR;
+
+ /* Create the chunking info structure */
+ mc->channel = channel;
+ mc->requestId = requestId;
+ mc->chunksSoFar = 0;
+ mc->messageSizeSoFar = 0;
+ mc->final = false;
+ mc->messageBuffer = UA_BYTESTRING_NULL;
+ mc->messageType = messageType;
+
+ /* Minimum required size */
+ if(connection->localConf.sendBufferSize <= UA_SECURE_MESSAGE_HEADER_LENGTH)
+ return UA_STATUSCODE_BADRESPONSETOOLARGE;
+
+ /* Allocate the message buffer */
+ UA_StatusCode retval =
+ connection->getSendBuffer(connection, connection->localConf.sendBufferSize,
+ &mc->messageBuffer);
+ if(retval != UA_STATUSCODE_GOOD)
+ return retval;
+
+ /* Hide bytes for header, padding and signature */
+ setBufPos(mc);
+ return UA_STATUSCODE_GOOD;
+}
+
+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) {
+ /* TODO: Send the abort message */
+ if(mc->messageBuffer.length > 0) {
+ UA_Connection *connection = mc->channel->connection;
+ connection->releaseSendBuffer(connection, &mc->messageBuffer);
+ }
+ }
+ return retval;
+}
+
+UA_StatusCode
+UA_MessageContext_finish(UA_MessageContext *mc) {
+ mc->final = true;
+ return sendSymmetricChunk(mc);
+}
+
+void
+UA_MessageContext_abort(UA_MessageContext *mc) {
+ UA_Connection *connection = mc->channel->connection;
+ connection->releaseSendBuffer(connection, &mc->messageBuffer);
+}
+
+UA_StatusCode
+UA_SecureChannel_sendSymmetricMessage(UA_SecureChannel *channel, UA_UInt32 requestId,
+ UA_MessageType messageType, void *payload,
+ const UA_DataType *payloadType) {
+ if(!channel || !payload || !payloadType)
+ return UA_STATUSCODE_BADINTERNALERROR;
+
+ if(channel->connection) {
+ if(channel->connection->state == UA_CONNECTION_CLOSED)
+ return UA_STATUSCODE_BADCONNECTIONCLOSED;
+ }
+
+ UA_MessageContext mc;
+ UA_StatusCode retval = UA_MessageContext_begin(&mc, channel, requestId, messageType);
+ if(retval != UA_STATUSCODE_GOOD)
+ 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_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;
+
+ retval = UA_MessageContext_encode(&mc, payload, payloadType);
+ if(retval != UA_STATUSCODE_GOOD)
+ return retval;
+
+ return UA_MessageContext_finish(&mc);
+}
+
+/*****************************/
+/* Assemble Complete Message */
+/*****************************/
+
+static void
+UA_SecureChannel_removeChunks(UA_SecureChannel *channel, UA_UInt32 requestId) {
+ struct MessageEntry *me;
+ LIST_FOREACH(me, &channel->chunks, pointers) {
+ if(me->requestId == requestId) {
+ struct ChunkPayload *cp, *temp_cp;
+ SIMPLEQ_FOREACH_SAFE(cp, &me->chunkPayload, pointers, temp_cp) {
+ UA_ByteString_deleteMembers(&cp->bytes);
+ UA_free(cp);
+ }
+ LIST_REMOVE(me, pointers);
+ UA_free(me);
+ return;
+ }
+ }
+}
+
+static UA_StatusCode
+appendChunk(struct MessageEntry *messageEntry, const UA_ByteString *chunkBody) {
+
+ struct ChunkPayload* cp = (struct ChunkPayload*)UA_malloc(sizeof(struct ChunkPayload));
+ UA_StatusCode retval = UA_ByteString_copy(chunkBody, &cp->bytes);
+ if (retval != UA_STATUSCODE_GOOD)
+ return retval;
+
+ SIMPLEQ_INSERT_TAIL(&messageEntry->chunkPayload, cp, pointers);
+ messageEntry->chunkPayloadSize += chunkBody->length;
+ return UA_STATUSCODE_GOOD;
+}
+
+static UA_StatusCode
+UA_SecureChannel_appendChunk(UA_SecureChannel *channel, UA_UInt32 requestId,
+ const UA_ByteString *chunkBody) {
+ struct MessageEntry *me;
+ LIST_FOREACH(me, &channel->chunks, pointers) {
+ if(me->requestId == requestId)
+ break;
+ }
+
+ /* No chunkentry on the channel, create one */
+ if(!me) {
+ me = (struct MessageEntry *)UA_malloc(sizeof(struct MessageEntry));
+ if(!me)
+ return UA_STATUSCODE_BADOUTOFMEMORY;
+ memset(me, 0, sizeof(struct MessageEntry));
+ me->requestId = requestId;
+ SIMPLEQ_INIT(&me->chunkPayload);
+ LIST_INSERT_HEAD(&channel->chunks, me, pointers);
+ }
+
+ return appendChunk(me, chunkBody);
+}
+
+static UA_StatusCode
+UA_SecureChannel_finalizeChunk(UA_SecureChannel *channel, UA_UInt32 requestId,
+ const UA_ByteString *chunkBody, UA_MessageType messageType,
+ UA_ProcessMessageCallback callback, void *application) {
+ struct MessageEntry *messageEntry;
+ LIST_FOREACH(messageEntry, &channel->chunks, pointers) {
+ if(messageEntry->requestId == requestId)
+ break;
+ }
+
+ UA_ByteString bytes;
+ if(!messageEntry) {
+ bytes = *chunkBody;
+ } else {
+ UA_StatusCode retval = appendChunk(messageEntry, chunkBody);
+ if(retval != UA_STATUSCODE_GOOD)
+ return retval;
+
+ UA_ByteString_init(&bytes);
+
+ bytes.data = (UA_Byte*) UA_malloc(messageEntry->chunkPayloadSize);
+ if (!bytes.data)
+ return UA_STATUSCODE_BADOUTOFMEMORY;
+
+ struct ChunkPayload *cp, *temp_cp;
+ size_t curPos = 0;
+ SIMPLEQ_FOREACH_SAFE(cp, &messageEntry->chunkPayload, pointers, temp_cp) {
+ memcpy(&bytes.data[curPos], cp->bytes.data, cp->bytes.length);
+ curPos += cp->bytes.length;
+ UA_ByteString_deleteMembers(&cp->bytes);
+ UA_free(cp);
+ }
+
+ bytes.length = messageEntry->chunkPayloadSize;
+
+ LIST_REMOVE(messageEntry, pointers);
+ UA_free(messageEntry);
+ }
+
+ UA_StatusCode retval = callback(application, channel, messageType, requestId, &bytes);
+ if(messageEntry)
+ UA_ByteString_deleteMembers(&bytes);
+ return retval;
+}
+
+/****************************/
+/* Process a received Chunk */
+/****************************/
+
+static UA_StatusCode
+decryptChunk(UA_SecureChannel *channel, const UA_SecurityPolicyCryptoModule *cryptoModule,
+ UA_ByteString *chunk, size_t offset, UA_UInt32 *requestId, UA_UInt32 *sequenceNumber,
+ UA_ByteString *payload, UA_MessageType messageType) {
+ UA_StatusCode retval = UA_STATUSCODE_GOOD;
+ const UA_SecurityPolicy *securityPolicy = channel->securityPolicy;
+ size_t chunkSizeAfterDecryption = chunk->length;
+
+ /* Decrypt the chunk. Always decrypt opn messages if mode not none */
+ if(channel->securityMode == UA_MESSAGESECURITYMODE_SIGNANDENCRYPT ||
+ messageType == UA_MESSAGETYPE_OPN) {
+ UA_ByteString cipherText = {chunk->length - offset, chunk->data + offset};
+ size_t sizeBeforeDecryption = cipherText.length;
+ retval = cryptoModule->encryptionAlgorithm.decrypt(securityPolicy, channel->channelContext, &cipherText);
+ chunkSizeAfterDecryption -= (sizeBeforeDecryption - cipherText.length);
+ if(retval != UA_STATUSCODE_GOOD)
+ return retval;
+ }
+
+ /* Verify the chunk signature */
+ size_t sigsize = 0;
+ size_t paddingSize = 0;
+ if(channel->securityMode == UA_MESSAGESECURITYMODE_SIGN ||
+ channel->securityMode == UA_MESSAGESECURITYMODE_SIGNANDENCRYPT ||
+ messageType == UA_MESSAGETYPE_OPN) {
+ /* Compute the padding size */
+ sigsize = cryptoModule->signatureAlgorithm.getRemoteSignatureSize(securityPolicy, channel->channelContext);
+
+ if(channel->securityMode == UA_MESSAGESECURITYMODE_SIGNANDENCRYPT ||
+ (messageType == UA_MESSAGETYPE_OPN &&
+ channel->securityMode > UA_MESSAGESECURITYMODE_NONE)) {
+ paddingSize = (size_t)chunk->data[chunkSizeAfterDecryption - sigsize - 1];
+
+ size_t keyLength =
+ cryptoModule->encryptionAlgorithm.getRemoteKeyLength(securityPolicy, channel->channelContext);
+ if(keyLength > 2048) {
+ paddingSize <<= 8; /* Extra padding size */
+ paddingSize += chunk->data[chunkSizeAfterDecryption - sigsize - 2];
+ // see comment below but for extraPaddingSize
+ paddingSize += 1;
+ }
+
+ // we need to add one to the padding size since the paddingSize byte itself need to be removed as well.
+ // TODO: write unit test for correct padding calculation
+ paddingSize += 1;
+ }
+ if(offset + paddingSize + sigsize >= chunkSizeAfterDecryption)
+ return UA_STATUSCODE_BADSECURITYCHECKSFAILED;
+
+ /* Verify the signature */
+ const UA_ByteString chunkDataToVerify = {chunkSizeAfterDecryption - sigsize, chunk->data};
+ const UA_ByteString signature = {sigsize, chunk->data + chunkSizeAfterDecryption - sigsize};
+ retval = cryptoModule->signatureAlgorithm.verify(securityPolicy, channel->channelContext,
+ &chunkDataToVerify, &signature);
+#ifdef UA_ENABLE_UNIT_TEST_FAILURE_HOOKS
+ retval |= decrypt_verifySignatureFailure;
+#endif
+ if(retval != UA_STATUSCODE_GOOD)
+ return retval;
+ }
+
+ /* Decode the sequence header */
+ UA_SequenceHeader sequenceHeader;
+ retval = UA_SequenceHeader_decodeBinary(chunk, &offset, &sequenceHeader);
+ if(retval != UA_STATUSCODE_GOOD)
+ return retval;
+
+ if(offset + paddingSize + sigsize >= chunk->length)
+ return UA_STATUSCODE_BADSECURITYCHECKSFAILED;
+
+ *requestId = sequenceHeader.requestId;
+ *sequenceNumber = sequenceHeader.sequenceNumber;
+ payload->data = chunk->data + offset;
+ payload->length = chunkSizeAfterDecryption - offset - sigsize - paddingSize;
+ return UA_STATUSCODE_GOOD;
+}
+
+typedef UA_StatusCode(*UA_SequenceNumberCallback)(UA_SecureChannel *channel,
+ UA_UInt32 sequenceNumber);
+
+static UA_StatusCode
+processSequenceNumberAsym(UA_SecureChannel *const channel, UA_UInt32 sequenceNumber) {
+ channel->receiveSequenceNumber = sequenceNumber;
+
+ return UA_STATUSCODE_GOOD;
+}
+
+static UA_StatusCode
+processSequenceNumberSym(UA_SecureChannel *const channel, UA_UInt32 sequenceNumber) {
+ /* Failure mode hook for unit tests */
+#ifdef UA_ENABLE_UNIT_TEST_FAILURE_HOOKS
+ 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
+ return UA_STATUSCODE_BADSECURITYCHECKSFAILED;
+ }
+ ++channel->receiveSequenceNumber;
+ return UA_STATUSCODE_GOOD;
+}
+
+static UA_StatusCode
+checkAsymHeader(UA_SecureChannel *const channel,
+ UA_AsymmetricAlgorithmSecurityHeader *const asymHeader) {
+ UA_StatusCode retval = UA_STATUSCODE_GOOD;
+ const UA_SecurityPolicy *const securityPolicy = channel->securityPolicy;
+
+ if(!UA_ByteString_equal(&securityPolicy->policyUri, &asymHeader->securityPolicyUri)) {
+ return UA_STATUSCODE_BADSECURITYPOLICYREJECTED;
+ }
+
+ // TODO: Verify certificate using certificate plugin. This will come with a new PR
+ /* Something like this
+ retval = certificateManager->verify(certificateStore??, &asymHeader->senderCertificate);
+ if(retval != UA_STATUSCODE_GOOD)
+ return retval;
+ */
+ retval = securityPolicy->asymmetricModule.
+ compareCertificateThumbprint(securityPolicy, &asymHeader->receiverCertificateThumbprint);
+ if(retval != UA_STATUSCODE_GOOD) {
+ return retval;
+ }
+
+ return UA_STATUSCODE_GOOD;
+}
+
+static UA_StatusCode
+checkPreviousToken(UA_SecureChannel *const channel, const UA_UInt32 tokenId) {
+ if(tokenId != channel->previousSecurityToken.tokenId)
+ return UA_STATUSCODE_BADSECURECHANNELTOKENUNKNOWN;
+
+ UA_DateTime timeout = channel->previousSecurityToken.createdAt +
+ (UA_DateTime)((UA_Double)channel->previousSecurityToken.revisedLifetime *
+ (UA_Double)UA_DATETIME_MSEC *
+ 1.25);
+
+ if(timeout < UA_DateTime_nowMonotonic()) {
+ return UA_STATUSCODE_BADSECURECHANNELTOKENUNKNOWN;
+ }
+
+ return UA_STATUSCODE_GOOD;
+}
+
+static UA_StatusCode
+checkSymHeader(UA_SecureChannel *const channel,
+ const UA_UInt32 tokenId, UA_Boolean allowPreviousToken) {
+
+ if(tokenId == channel->securityToken.tokenId) {
+ if(channel->state == UA_SECURECHANNELSTATE_OPEN &&
+ (channel->securityToken.createdAt +
+ (channel->securityToken.revisedLifetime * UA_DATETIME_MSEC)) < UA_DateTime_nowMonotonic()) {
+ UA_SecureChannel_deleteMembersCleanup(channel);
+ return UA_STATUSCODE_BADSECURECHANNELCLOSED;
+ }
+ }
+
+ if(tokenId != channel->securityToken.tokenId) {
+ if(tokenId != channel->nextSecurityToken.tokenId) {
+ if(allowPreviousToken)
+ return checkPreviousToken(channel, tokenId);
+ else
+ return UA_STATUSCODE_BADSECURECHANNELTOKENUNKNOWN;
+ }
+ return UA_SecureChannel_revolveTokens(channel);
+ }
+
+ if(channel->previousSecurityToken.tokenId != 0) {
+ UA_StatusCode retval = UA_SecureChannel_generateRemoteKeys(channel, channel->securityPolicy);
+ UA_ChannelSecurityToken_deleteMembers(&channel->previousSecurityToken);
+ return retval;
+ }
+
+ return UA_STATUSCODE_GOOD;
+}
+
+UA_StatusCode
+UA_SecureChannel_processChunk(UA_SecureChannel *channel, UA_ByteString *chunk,
+ UA_ProcessMessageCallback callback,
+ void *application, UA_Boolean allowPreviousToken) {
+ /* Decode message header */
+ size_t offset = 0;
+ UA_SecureConversationMessageHeader messageHeader;
+ UA_StatusCode retval =
+ UA_SecureConversationMessageHeader_decodeBinary(chunk, &offset, &messageHeader);
+ if(retval != UA_STATUSCODE_GOOD)
+ return retval;
+
+#if !defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION)
+ /* The wrong ChannelId. Non-opened channels have the id zero. */
+ if(messageHeader.secureChannelId != channel->securityToken.channelId &&
+ channel->state != UA_SECURECHANNELSTATE_FRESH)
+ return UA_STATUSCODE_BADSECURECHANNELIDINVALID;
+#endif
+
+ UA_MessageType messageType = (UA_MessageType)
+ (messageHeader.messageHeader.messageTypeAndChunkType & UA_BITMASK_MESSAGETYPE);
+ UA_ChunkType chunkType = (UA_ChunkType)
+ (messageHeader.messageHeader.messageTypeAndChunkType & UA_BITMASK_CHUNKTYPE);
+
+ /* ERR message (not encrypted) */
+ UA_UInt32 requestId = 0;
+ UA_UInt32 sequenceNumber = 0;
+ UA_ByteString chunkPayload;
+ const UA_SecurityPolicyCryptoModule *cryptoModule = NULL;
+ UA_SequenceNumberCallback sequenceNumberCallback = NULL;
+
+ switch(messageType) {
+ case UA_MESSAGETYPE_ERR: {
+ if(chunkType != UA_CHUNKTYPE_FINAL)
+ return UA_STATUSCODE_BADTCPMESSAGETYPEINVALID;
+ chunkPayload.length = chunk->length - offset;
+ chunkPayload.data = chunk->data + offset;
+ return callback(application, channel, messageType, requestId, &chunkPayload);
+ }
+
+ case UA_MESSAGETYPE_MSG:
+ case UA_MESSAGETYPE_CLO: {
+ /* Decode and check the symmetric security header (tokenId) */
+ UA_SymmetricAlgorithmSecurityHeader symmetricSecurityHeader;
+ UA_SymmetricAlgorithmSecurityHeader_init(&symmetricSecurityHeader);
+ retval = UA_SymmetricAlgorithmSecurityHeader_decodeBinary(chunk, &offset,
+ &symmetricSecurityHeader);
+ if(retval != UA_STATUSCODE_GOOD)
+ return retval;
+
+#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
+ /* Help fuzzing by always setting the correct tokenId */
+ symmetricSecurityHeader.tokenId = channel->securityToken.tokenId;
+#endif
+
+ retval = checkSymHeader(channel, symmetricSecurityHeader.tokenId, allowPreviousToken);
+ if(retval != UA_STATUSCODE_GOOD)
+ return retval;
+
+ cryptoModule = &channel->securityPolicy->symmetricModule.cryptoModule;
+ sequenceNumberCallback = processSequenceNumberSym;
+ break;
+ }
+ case UA_MESSAGETYPE_OPN: {
+ /* Chunking not allowed for OPN */
+ if(chunkType != UA_CHUNKTYPE_FINAL)
+ return UA_STATUSCODE_BADTCPMESSAGETYPEINVALID;
+
+ /* Decode the asymmetric algorithm security header and call the callback
+ * to perform checks. */
+ UA_AsymmetricAlgorithmSecurityHeader asymHeader;
+ UA_AsymmetricAlgorithmSecurityHeader_init(&asymHeader);
+ offset = UA_SECURE_CONVERSATION_MESSAGE_HEADER_LENGTH;
+ retval = UA_AsymmetricAlgorithmSecurityHeader_decodeBinary(chunk, &offset, &asymHeader);
+ if(retval != UA_STATUSCODE_GOOD)
+ return retval;
+
+ retval = checkAsymHeader(channel, &asymHeader);
+ UA_AsymmetricAlgorithmSecurityHeader_deleteMembers(&asymHeader);
+ if(retval != UA_STATUSCODE_GOOD)
+ return retval;
+
+ cryptoModule = &channel->securityPolicy->asymmetricModule.cryptoModule;
+ sequenceNumberCallback = processSequenceNumberAsym;
+ break;
+ }
+ default:return UA_STATUSCODE_BADTCPMESSAGETYPEINVALID;
+ }
+
+ /* Decrypt message */
+ UA_assert(cryptoModule != NULL);
+ retval = decryptChunk(channel, cryptoModule, chunk, offset, &requestId,
+ &sequenceNumber, &chunkPayload, messageType);
+ if(retval != UA_STATUSCODE_GOOD)
+ return retval;
+
+ /* Check the sequence number */
+ if(sequenceNumberCallback == NULL)
+ return UA_STATUSCODE_BADINTERNALERROR;
+ retval = sequenceNumberCallback(channel, sequenceNumber);
+
+ /* Skip sequence number checking for fuzzer to improve coverage */
+ if(retval != UA_STATUSCODE_GOOD) {
+#if !defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION)
+ return retval;
+#else
+ retval = UA_STATUSCODE_GOOD;
+#endif
+ }
+
+ /* Process the payload */
+ if(chunkType == UA_CHUNKTYPE_FINAL) {
+ retval = UA_SecureChannel_finalizeChunk(channel, requestId, &chunkPayload,
+ messageType, callback, application);
+ } else if(chunkType == UA_CHUNKTYPE_INTERMEDIATE) {
+ retval = UA_SecureChannel_appendChunk(channel, requestId, &chunkPayload);
+ } else if(chunkType == UA_CHUNKTYPE_ABORT) {
+ UA_SecureChannel_removeChunks(channel, requestId);
+ } else {
+ retval = UA_STATUSCODE_BADTCPMESSAGETYPEINVALID;
+ }
+ return retval;
+}
+
+/* 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/jvoe/open62541/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
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * Copyright 2018 (c) Julius Pfrommer, Fraunhofer IOSB
+ * Copyright 2018 (c) Thomas Stalder, Blue Time Concept SA
+ */
+
+#ifdef UA_ENABLE_SUBSCRIPTIONS
+#endif
+
+#define UA_SESSION_NONCELENTH 32
+
+void UA_Session_init(UA_Session *session) {
+ memset(session, 0, sizeof(UA_Session));
+ session->availableContinuationPoints = UA_MAXCONTINUATIONPOINTS;
+#ifdef UA_ENABLE_SUBSCRIPTIONS
+ SIMPLEQ_INIT(&session->responseQueue);
+#endif
+}
+
+#ifdef UA_ENABLE_SUBSCRIPTIONS
+static void
+deleteSubscription(UA_Server *server, UA_Session *session,
+ UA_Subscription *sub) {
+ UA_Subscription_deleteMembers(server, sub);
+
+ /* Add a delayed callback to remove the subscription when the currently
+ * scheduled jobs have completed */
+ UA_StatusCode retval = UA_Server_delayedFree(server, sub);
+ if(retval != UA_STATUSCODE_GOOD) {
+ UA_LOG_WARNING_SESSION(server->config.logger, session,
+ "Could not remove subscription with error code %s",
+ UA_StatusCode_name(retval));
+ }
+
+ /* Remove from the session */
+ LIST_REMOVE(sub, listEntry);
+ UA_assert(session->numSubscriptions > 0);
+ session->numSubscriptions--;
+}
+#endif
+
+void UA_Session_deleteMembersCleanup(UA_Session *session, UA_Server *server) {
+ 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);
+ struct ContinuationPointEntry *cp, *temp;
+ LIST_FOREACH_SAFE(cp, &session->continuationPoints, pointers, temp) {
+ LIST_REMOVE(cp, pointers);
+ UA_ByteString_deleteMembers(&cp->identifier);
+ UA_BrowseDescription_deleteMembers(&cp->browseDescription);
+ UA_free(cp);
+ }
+
+#ifdef UA_ENABLE_SUBSCRIPTIONS
+ UA_Subscription *sub, *sub_tmp;
+ LIST_FOREACH_SAFE(sub, &session->serverSubscriptions, listEntry, sub_tmp) {
+ deleteSubscription(server, session, sub);
+ }
+#endif
+}
+
+void UA_Session_attachToSecureChannel(UA_Session *session, UA_SecureChannel *channel) {
+ LIST_INSERT_HEAD(&channel->sessions, &session->header, pointers);
+ session->header.channel = channel;
+}
+
+void UA_Session_detachFromSecureChannel(UA_Session *session) {
+ if(!session->header.channel)
+ return;
+ session->header.channel = NULL;
+ LIST_REMOVE(&session->header, pointers);
+}
+
+UA_StatusCode
+UA_Session_generateNonce(UA_Session *session) {
+ UA_SecureChannel *channel = session->header.channel;
+ if(!channel || !channel->securityPolicy)
+ return UA_STATUSCODE_BADINTERNALERROR;
+
+ /* Is the length of the previous nonce correct? */
+ if(session->serverNonce.length != UA_SESSION_NONCELENTH) {
+ UA_ByteString_deleteMembers(&session->serverNonce);
+ UA_StatusCode retval =
+ UA_ByteString_allocBuffer(&session->serverNonce, UA_SESSION_NONCELENTH);
+ if(retval != UA_STATUSCODE_GOOD)
+ return retval;
+ }
+
+ return channel->securityPolicy->symmetricModule.
+ generateNonce(channel->securityPolicy, &session->serverNonce);
+}
+
+void UA_Session_updateLifetime(UA_Session *session) {
+ session->validTill = UA_DateTime_nowMonotonic() +
+ (UA_DateTime)(session->timeout * UA_DATETIME_MSEC);
+}
+
+#ifdef UA_ENABLE_SUBSCRIPTIONS
+
+void UA_Session_addSubscription(UA_Session *session, UA_Subscription *newSubscription) {
+ newSubscription->subscriptionId = ++session->lastSubscriptionId;
+
+ LIST_INSERT_HEAD(&session->serverSubscriptions, newSubscription, listEntry);
+ session->numSubscriptions++;
+}
+
+UA_StatusCode
+UA_Session_deleteSubscription(UA_Server *server, UA_Session *session,
+ UA_UInt32 subscriptionId) {
+ UA_Subscription *sub = UA_Session_getSubscriptionById(session, subscriptionId);
+ if(!sub)
+ return UA_STATUSCODE_BADSUBSCRIPTIONIDINVALID;
+
+ deleteSubscription(server, session, sub);
+ return UA_STATUSCODE_GOOD;
+}
+
+UA_Subscription *
+UA_Session_getSubscriptionById(UA_Session *session, UA_UInt32 subscriptionId) {
+ UA_Subscription *sub;
+ LIST_FOREACH(sub, &session->serverSubscriptions, listEntry) {
+ if(sub->subscriptionId == subscriptionId)
+ break;
+ }
+ return sub;
+}
+
+UA_PublishResponseEntry*
+UA_Session_dequeuePublishReq(UA_Session *session) {
+ UA_PublishResponseEntry* entry = SIMPLEQ_FIRST(&session->responseQueue);
+ if(entry) {
+ SIMPLEQ_REMOVE_HEAD(&session->responseQueue, listEntry);
+ session->numPublishReq--;
+ }
+ return entry;
+}
+
+void
+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++;
+}
+
+#endif
+
+/*********************************** amalgamated original file "/home/jvoe/open62541/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-2017 (c) Julius Pfrommer, Fraunhofer IOSB
+ * Copyright 2015-2016 (c) Sten Grüner
+ * Copyright 2015 (c) Chris Iatrou
+ * Copyright 2015, 2017 (c) Florian Palm
+ * Copyright 2015 (c) Oleksiy Vasylyev
+ * Copyright 2016-2017 (c) Stefan Profanter, fortiss GmbH
+ * Copyright 2017 (c) Julian Grothoff
+ */
+
+
+/* There is no UA_Node_new() method here. Creating nodes is part of the
+ * NodeStore layer */
+
+void UA_Node_deleteMembers(UA_Node *node) {
+ /* Delete standard content */
+ UA_NodeId_deleteMembers(&node->nodeId);
+ UA_QualifiedName_deleteMembers(&node->browseName);
+ UA_LocalizedText_deleteMembers(&node->displayName);
+ UA_LocalizedText_deleteMembers(&node->description);
+
+ /* Delete references */
+ UA_Node_deleteReferences(node);
+
+ /* Delete unique content of the nodeclass */
+ switch(node->nodeClass) {
+ case UA_NODECLASS_OBJECT:
+ break;
+ case UA_NODECLASS_METHOD:
+ break;
+ case UA_NODECLASS_OBJECTTYPE:
+ break;
+ case UA_NODECLASS_VARIABLE:
+ case UA_NODECLASS_VARIABLETYPE: {
+ UA_VariableNode *p = (UA_VariableNode*)node;
+ UA_NodeId_deleteMembers(&p->dataType);
+ UA_Array_delete(p->arrayDimensions, p->arrayDimensionsSize,
+ &UA_TYPES[UA_TYPES_INT32]);
+ p->arrayDimensions = NULL;
+ p->arrayDimensionsSize = 0;
+ if(p->valueSource == UA_VALUESOURCE_DATA)
+ UA_DataValue_deleteMembers(&p->value.data.value);
+ break;
+ }
+ case UA_NODECLASS_REFERENCETYPE: {
+ UA_ReferenceTypeNode *p = (UA_ReferenceTypeNode*)node;
+ UA_LocalizedText_deleteMembers(&p->inverseName);
+ break;
+ }
+ case UA_NODECLASS_DATATYPE:
+ break;
+ case UA_NODECLASS_VIEW:
+ break;
+ default:
+ break;
+ }
+}
+
+static UA_StatusCode
+UA_ObjectNode_copy(const UA_ObjectNode *src, UA_ObjectNode *dst) {
+ dst->eventNotifier = src->eventNotifier;
+ return UA_STATUSCODE_GOOD;
+}
+
+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]);
+ if(retval != UA_STATUSCODE_GOOD)
+ return retval;
+ dst->arrayDimensionsSize = src->arrayDimensionsSize;
+ retval = UA_NodeId_copy(&src->dataType, &dst->dataType);
+ dst->valueRank = src->valueRank;
+ dst->valueSource = src->valueSource;
+ if(src->valueSource == UA_VALUESOURCE_DATA) {
+ retval |= UA_DataValue_copy(&src->value.data.value,
+ &dst->value.data.value);
+ dst->value.data.callback = src->value.data.callback;
+ } else
+ dst->value.dataSource = src->value.dataSource;
+ return retval;
+}
+
+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;
+}
+
+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;
+}
+
+static UA_StatusCode
+UA_MethodNode_copy(const UA_MethodNode *src, UA_MethodNode *dst) {
+ dst->executable = src->executable;
+ dst->method = src->method;
+ return UA_STATUSCODE_GOOD;
+}
+
+static UA_StatusCode
+UA_ObjectTypeNode_copy(const UA_ObjectTypeNode *src, UA_ObjectTypeNode *dst) {
+ dst->isAbstract = src->isAbstract;
+ dst->lifecycle = src->lifecycle;
+ return UA_STATUSCODE_GOOD;
+}
+
+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;
+}
+
+static UA_StatusCode
+UA_DataTypeNode_copy(const UA_DataTypeNode *src, UA_DataTypeNode *dst) {
+ dst->isAbstract = src->isAbstract;
+ return UA_STATUSCODE_GOOD;
+}
+
+static UA_StatusCode
+UA_ViewNode_copy(const UA_ViewNode *src, UA_ViewNode *dst) {
+ dst->containsNoLoops = src->containsNoLoops;
+ dst->eventNotifier = src->eventNotifier;
+ return UA_STATUSCODE_GOOD;
+}
+
+UA_StatusCode
+UA_Node_copy(const UA_Node *src, UA_Node *dst) {
+ if(src->nodeClass != dst->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;
+ if(retval != UA_STATUSCODE_GOOD) {
+ UA_Node_deleteMembers(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) {
+ UA_Node_deleteMembers(dst);
+ return UA_STATUSCODE_BADOUTOFMEMORY;
+ }
+ dst->referencesSize = src->referencesSize;
+
+ for(size_t i = 0; i < src->referencesSize; ++i) {
+ UA_NodeReferenceKind *srefs = &src->references[i];
+ UA_NodeReferenceKind *drefs = &dst->references[i];
+ drefs->isInverse = srefs->isInverse;
+ retval = UA_NodeId_copy(&srefs->referenceTypeId, &drefs->referenceTypeId);
+ if(retval != UA_STATUSCODE_GOOD)
+ break;
+ retval = UA_Array_copy(srefs->targetIds, srefs->targetIdsSize,
+ (void**)&drefs->targetIds,
+ &UA_TYPES[UA_TYPES_EXPANDEDNODEID]);
+ if(retval != UA_STATUSCODE_GOOD)
+ break;
+ drefs->targetIdsSize = srefs->targetIdsSize;
+ }
+ if(retval != UA_STATUSCODE_GOOD) {
+ UA_Node_deleteMembers(dst);
+ return retval;
+ }
+ }
+
+ /* Copy unique content of the nodeclass */
+ switch(src->nodeClass) {
+ case UA_NODECLASS_OBJECT:
+ retval = UA_ObjectNode_copy((const UA_ObjectNode*)src, (UA_ObjectNode*)dst);
+ break;
+ case UA_NODECLASS_VARIABLE:
+ retval = UA_VariableNode_copy((const UA_VariableNode*)src, (UA_VariableNode*)dst);
+ break;
+ case UA_NODECLASS_METHOD:
+ retval = UA_MethodNode_copy((const UA_MethodNode*)src, (UA_MethodNode*)dst);
+ break;
+ case UA_NODECLASS_OBJECTTYPE:
+ retval = UA_ObjectTypeNode_copy((const UA_ObjectTypeNode*)src, (UA_ObjectTypeNode*)dst);
+ break;
+ case UA_NODECLASS_VARIABLETYPE:
+ retval = UA_VariableTypeNode_copy((const UA_VariableTypeNode*)src, (UA_VariableTypeNode*)dst);
+ break;
+ case UA_NODECLASS_REFERENCETYPE:
+ retval = UA_ReferenceTypeNode_copy((const UA_ReferenceTypeNode*)src, (UA_ReferenceTypeNode*)dst);
+ break;
+ case UA_NODECLASS_DATATYPE:
+ retval = UA_DataTypeNode_copy((const UA_DataTypeNode*)src, (UA_DataTypeNode*)dst);
+ break;
+ case UA_NODECLASS_VIEW:
+ retval = UA_ViewNode_copy((const UA_ViewNode*)src, (UA_ViewNode*)dst);
+ break;
+ default:
+ break;
+ }
+
+ if(retval != UA_STATUSCODE_GOOD)
+ UA_Node_deleteMembers(dst);
+
+ return retval;
+}
+
+UA_Node *
+UA_Node_copy_alloc(const UA_Node *src) {
+ // use dstPtr to trick static code analysis in accepting dirty cast
+ void *dstPtr;
+ switch(src->nodeClass) {
+ case UA_NODECLASS_OBJECT:
+ dstPtr = UA_malloc(sizeof(UA_ObjectNode));
+ break;
+ case UA_NODECLASS_VARIABLE:
+ dstPtr =UA_malloc(sizeof(UA_VariableNode));
+ break;
+ case UA_NODECLASS_METHOD:
+ dstPtr = UA_malloc(sizeof(UA_MethodNode));
+ break;
+ case UA_NODECLASS_OBJECTTYPE:
+ dstPtr = UA_malloc(sizeof(UA_ObjectTypeNode));
+ break;
+ case UA_NODECLASS_VARIABLETYPE:
+ dstPtr = UA_malloc(sizeof(UA_VariableTypeNode));
+ break;
+ case UA_NODECLASS_REFERENCETYPE:
+ dstPtr = UA_malloc(sizeof(UA_ReferenceTypeNode));
+ break;
+ case UA_NODECLASS_DATATYPE:
+ dstPtr = UA_malloc(sizeof(UA_DataTypeNode));
+ break;
+ case UA_NODECLASS_VIEW:
+ dstPtr = UA_malloc(sizeof(UA_ViewNode));
+ break;
+ default:
+ return NULL;
+ }
+ UA_Node *dst = (UA_Node*)dstPtr;
+ dst->nodeClass = src->nodeClass;
+
+ UA_StatusCode retval = UA_Node_copy(src, dst);
+ if(retval != UA_STATUSCODE_GOOD) {
+ UA_free(dst);
+ return NULL;
+ }
+ return dst;
+}
+/******************************/
+/* Copy Attributes into Nodes */
+/******************************/
+
+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 = UA_LocalizedText_copy(&attr->displayName,
+ &node->displayName);
+ retval |= UA_LocalizedText_copy(&attr->description, &node->description);
+ node->writeMask = attr->writeMask;
+ return retval;
+}
+
+static UA_StatusCode
+copyCommonVariableAttributes(UA_VariableNode *node,
+ const UA_VariableAttributes *attr) {
+ /* Copy the array dimensions */
+ UA_StatusCode retval =
+ UA_Array_copy(attr->arrayDimensions, attr->arrayDimensionsSize,
+ (void**)&node->arrayDimensions, &UA_TYPES[UA_TYPES_UINT32]);
+ if(retval != UA_STATUSCODE_GOOD)
+ return retval;
+ node->arrayDimensionsSize = attr->arrayDimensionsSize;
+
+ /* Data type and value rank */
+ retval |= UA_NodeId_copy(&attr->dataType, &node->dataType);
+ node->valueRank = attr->valueRank;
+
+ /* Copy the value */
+ node->valueSource = UA_VALUESOURCE_DATA;
+ UA_NodeId extensionObject = UA_NODEID_NUMERIC(0, UA_NS0ID_STRUCTURE);
+ /* if we have an extension object which is still encoded (e.g. from the nodeset compiler)
+ * we need to decode it and set the decoded value instead of the encoded object */
+ UA_Boolean valueSet = false;
+ if(attr->value.type != NULL && UA_NodeId_equal(&attr->value.type->typeId, &extensionObject)) {
+
+ if (attr->value.data == UA_EMPTY_ARRAY_SENTINEL) {
+ /* do nothing since we got an empty array of extension objects */
+ return UA_STATUSCODE_GOOD;
+ }
+
+ const UA_ExtensionObject *obj = (const UA_ExtensionObject *)attr->value.data;
+ if(obj && obj->encoding == UA_EXTENSIONOBJECT_ENCODED_BYTESTRING) {
+
+ /* TODO: Once we generate type description in the nodeset compiler,
+ * UA_findDatatypeByBinary can be made internal to the decoding
+ * layer. */
+ const UA_DataType *type = UA_findDataTypeByBinary(&obj->content.encoded.typeId);
+
+ if(type) {
+ void *dst = UA_Array_new(attr->value.arrayLength, type);
+ if (!dst) {
+ return UA_STATUSCODE_BADOUTOFMEMORY;
+ }
+ uint8_t *tmpPos = (uint8_t *)dst;
+
+ for(size_t i=0; i<attr->value.arrayLength; i++) {
+ size_t offset =0;
+ const UA_ExtensionObject *curr = &((const UA_ExtensionObject *)attr->value.data)[i];
+ UA_StatusCode ret = UA_decodeBinary(&curr->content.encoded.body, &offset, tmpPos, type, 0, NULL);
+ if(ret != UA_STATUSCODE_GOOD) {
+ return ret;
+ }
+ tmpPos += type->memSize;
+ }
+
+ UA_Variant_setArray(&node->value.data.value.value, dst, attr->value.arrayLength, type);
+ valueSet = true;
+ }
+ }
+ }
+
+ if(!valueSet)
+ retval |= UA_Variant_copy(&attr->value, &node->value.data.value.value);
+
+ node->value.data.value.hasValue = true;
+
+ return retval;
+}
+
+static UA_StatusCode
+copyVariableNodeAttributes(UA_VariableNode *vnode,
+ const UA_VariableAttributes *attr) {
+ vnode->accessLevel = attr->accessLevel;
+ vnode->historizing = attr->historizing;
+ vnode->minimumSamplingInterval = attr->minimumSamplingInterval;
+ return copyCommonVariableAttributes(vnode, attr);
+}
+
+static UA_StatusCode
+copyVariableTypeNodeAttributes(UA_VariableTypeNode *vtnode,
+ const UA_VariableTypeAttributes *attr) {
+ vtnode->isAbstract = attr->isAbstract;
+ return copyCommonVariableAttributes((UA_VariableNode*)vtnode,
+ (const UA_VariableAttributes*)attr);
+}
+
+static UA_StatusCode
+copyObjectNodeAttributes(UA_ObjectNode *onode, const UA_ObjectAttributes *attr) {
+ onode->eventNotifier = attr->eventNotifier;
+ return UA_STATUSCODE_GOOD;
+}
+
+static UA_StatusCode
+copyReferenceTypeNodeAttributes(UA_ReferenceTypeNode *rtnode,
+ const UA_ReferenceTypeAttributes *attr) {
+ rtnode->isAbstract = attr->isAbstract;
+ rtnode->symmetric = attr->symmetric;
+ return UA_LocalizedText_copy(&attr->inverseName, &rtnode->inverseName);
+}
+
+static UA_StatusCode
+copyObjectTypeNodeAttributes(UA_ObjectTypeNode *otnode,
+ const UA_ObjectTypeAttributes *attr) {
+ otnode->isAbstract = attr->isAbstract;
+ return UA_STATUSCODE_GOOD;
+}
+
+static UA_StatusCode
+copyViewNodeAttributes(UA_ViewNode *vnode, const UA_ViewAttributes *attr) {
+ vnode->containsNoLoops = attr->containsNoLoops;
+ vnode->eventNotifier = attr->eventNotifier;
+ return UA_STATUSCODE_GOOD;
+}
+
+static UA_StatusCode
+copyDataTypeNodeAttributes(UA_DataTypeNode *dtnode,
+ const UA_DataTypeAttributes *attr) {
+ dtnode->isAbstract = attr->isAbstract;
+ return UA_STATUSCODE_GOOD;
+}
+
+static UA_StatusCode
+copyMethodNodeAttributes(UA_MethodNode *mnode,
+ const UA_MethodAttributes *attr) {
+ mnode->executable = attr->executable;
+ return UA_STATUSCODE_GOOD;
+}
+
+#define CHECK_ATTRIBUTES(TYPE) \
+ if(attributeType != &UA_TYPES[UA_TYPES_##TYPE]) { \
+ retval = UA_STATUSCODE_BADNODEATTRIBUTESINVALID; \
+ break; \
+ }
+
+UA_StatusCode
+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) {
+ case UA_NODECLASS_OBJECT:
+ CHECK_ATTRIBUTES(OBJECTATTRIBUTES);
+ retval = copyObjectNodeAttributes((UA_ObjectNode*)node,
+ (const UA_ObjectAttributes*)attributes);
+ break;
+ case UA_NODECLASS_VARIABLE:
+ CHECK_ATTRIBUTES(VARIABLEATTRIBUTES);
+ retval = copyVariableNodeAttributes((UA_VariableNode*)node,
+ (const UA_VariableAttributes*)attributes);
+ break;
+ case UA_NODECLASS_OBJECTTYPE:
+ CHECK_ATTRIBUTES(OBJECTTYPEATTRIBUTES);
+ retval = copyObjectTypeNodeAttributes((UA_ObjectTypeNode*)node,
+ (const UA_ObjectTypeAttributes*)attributes);
+ break;
+ case UA_NODECLASS_VARIABLETYPE:
+ CHECK_ATTRIBUTES(VARIABLETYPEATTRIBUTES);
+ retval = copyVariableTypeNodeAttributes((UA_VariableTypeNode*)node,
+ (const UA_VariableTypeAttributes*)attributes);
+ break;
+ case UA_NODECLASS_REFERENCETYPE:
+ CHECK_ATTRIBUTES(REFERENCETYPEATTRIBUTES);
+ retval = copyReferenceTypeNodeAttributes((UA_ReferenceTypeNode*)node,
+ (const UA_ReferenceTypeAttributes*)attributes);
+ break;
+ case UA_NODECLASS_DATATYPE:
+ CHECK_ATTRIBUTES(DATATYPEATTRIBUTES);
+ retval = copyDataTypeNodeAttributes((UA_DataTypeNode*)node,
+ (const UA_DataTypeAttributes*)attributes);
+ break;
+ case UA_NODECLASS_VIEW:
+ CHECK_ATTRIBUTES(VIEWATTRIBUTES);
+ retval = copyViewNodeAttributes((UA_ViewNode*)node,
+ (const UA_ViewAttributes*)attributes);
+ break;
+ case UA_NODECLASS_METHOD:
+ CHECK_ATTRIBUTES(METHODATTRIBUTES);
+ retval = copyMethodNodeAttributes((UA_MethodNode*)node,
+ (const UA_MethodAttributes*)attributes);
+ break;
+ case UA_NODECLASS_UNSPECIFIED:
+ default:
+ retval = UA_STATUSCODE_BADNODECLASSINVALID;
+ }
+
+ if(retval == UA_STATUSCODE_GOOD)
+ retval = copyStandardAttributes(node, (const UA_NodeAttributes*)attributes);
+ if(retval != UA_STATUSCODE_GOOD)
+ UA_Node_deleteMembers(node);
+ return retval;
+}
+
+/*********************/
+/* Manage References */
+/*********************/
+
+static UA_StatusCode
+addReferenceTarget(UA_NodeReferenceKind *refs, const UA_ExpandedNodeId *target) {
+ UA_ExpandedNodeId *targets =
+ (UA_ExpandedNodeId*) UA_realloc(refs->targetIds,
+ sizeof(UA_ExpandedNodeId) * (refs->targetIdsSize+1));
+ if(!targets)
+ return UA_STATUSCODE_BADOUTOFMEMORY;
+
+ refs->targetIds = targets;
+ UA_StatusCode retval =
+ UA_ExpandedNodeId_copy(target, &refs->targetIds[refs->targetIdsSize]);
+
+ if(retval == UA_STATUSCODE_GOOD) {
+ refs->targetIdsSize++;
+ } else if(refs->targetIdsSize == 0) {
+ /* We had zero references before (realloc was a malloc) */
+ UA_free(refs->targetIds);
+ refs->targetIds = NULL;
+ }
+ return retval;
+}
+
+static UA_StatusCode
+addReferenceKind(UA_Node *node, const UA_AddReferencesItem *item) {
+ UA_NodeReferenceKind *refs =
+ (UA_NodeReferenceKind*)UA_realloc(node->references,
+ sizeof(UA_NodeReferenceKind) * (node->referencesSize+1));
+ if(!refs)
+ return UA_STATUSCODE_BADOUTOFMEMORY;
+ node->references = refs;
+ UA_NodeReferenceKind *newRef = &refs[node->referencesSize];
+ memset(newRef, 0, sizeof(UA_NodeReferenceKind));
+
+ newRef->isInverse = !item->isForward;
+ UA_StatusCode retval = UA_NodeId_copy(&item->referenceTypeId, &newRef->referenceTypeId);
+ retval |= addReferenceTarget(newRef, &item->targetNodeId);
+
+ if(retval == UA_STATUSCODE_GOOD) {
+ node->referencesSize++;
+ } else {
+ UA_NodeId_deleteMembers(&newRef->referenceTypeId);
+ if(node->referencesSize == 0) {
+ UA_free(node->references);
+ node->references = NULL;
+ }
+ }
+ return retval;
+}
+
+UA_StatusCode
+UA_Node_addReference(UA_Node *node, const UA_AddReferencesItem *item) {
+ 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;
+ }
+ }
+ if(existingRefs != NULL) {
+ for(size_t i = 0; i < existingRefs->targetIdsSize; i++) {
+ if(UA_ExpandedNodeId_equal(&existingRefs->targetIds[i],
+ &item->targetNodeId)) {
+ return UA_STATUSCODE_BADDUPLICATEREFERENCENOTALLOWED;
+ }
+ }
+ return addReferenceTarget(existingRefs, &item->targetNodeId);
+ }
+ return addReferenceKind(node, item);
+}
+
+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)
+ continue;
+ if(!UA_NodeId_equal(&item->referenceTypeId, &refs->referenceTypeId))
+ continue;
+
+ for(size_t j = refs->targetIdsSize; j > 0; --j) {
+ if(!UA_NodeId_equal(&item->targetNodeId.nodeId, &refs->targetIds[j-1].nodeId))
+ continue;
+
+ /* Ok, delete the reference */
+ UA_ExpandedNodeId_deleteMembers(&refs->targetIds[j-1]);
+ refs->targetIdsSize--;
+
+ /* One matching target remaining */
+ if(refs->targetIdsSize > 0) {
+ if(j-1 != refs->targetIdsSize) // avoid valgrind error: Source
+ // and destination overlap in
+ // memcpy
+ refs->targetIds[j-1] = refs->targetIds[refs->targetIdsSize];
+ return UA_STATUSCODE_GOOD;
+ }
+
+ /* Remove refs */
+ UA_free(refs->targetIds);
+ UA_NodeId_deleteMembers(&refs->referenceTypeId);
+ node->referencesSize--;
+ if(node->referencesSize > 0) {
+ if(i-1 != node->referencesSize) // avoid valgrind error: Source
+ // and destination overlap in
+ // memcpy
+ node->references[i-1] = node->references[node->referencesSize];
+ return UA_STATUSCODE_GOOD;
+ }
+
+ /* Remove the node references */
+ UA_free(node->references);
+ node->references = NULL;
+ return UA_STATUSCODE_GOOD;
+ }
+ }
+ return UA_STATUSCODE_UNCERTAINREFERENCENOTDELETED;
+}
+
+void UA_Node_deleteReferences(UA_Node *node) {
+ for(size_t i = 0; i < node->referencesSize; ++i) {
+ UA_NodeReferenceKind *refs = &node->references[i];
+ UA_Array_delete(refs->targetIds, refs->targetIdsSize, &UA_TYPES[UA_TYPES_EXPANDEDNODEID]);
+ UA_NodeId_deleteMembers(&refs->referenceTypeId);
+ }
+ if(node->references)
+ UA_free(node->references);
+ node->references = NULL;
+ node->referencesSize = 0;
+}
+
+/*********************************** amalgamated original file "/home/jvoe/open62541/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
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * Copyright 2014-2018 (c) Julius Pfrommer, Fraunhofer IOSB
+ * Copyright 2014-2017 (c) Florian Palm
+ * Copyright 2015-2016 (c) Sten Grüner
+ * Copyright 2015-2016 (c) Chris Iatrou
+ * Copyright 2015 (c) LEvertz
+ * Copyright 2015-2016 (c) Oleksiy Vasylyev
+ * Copyright 2016 (c) Julian Grothoff
+ * Copyright 2016-2017 (c) Stefan Profanter, fortiss GmbH
+ * Copyright 2016 (c) Lorenz Haas
+ * Copyright 2017 (c) frax2222
+ * Copyright 2017 (c) Mark Giraud, Fraunhofer IOSB
+ */
+
+
+/**********************/
+/* Namespace Handling */
+/**********************/
+
+UA_UInt16 addNamespace(UA_Server *server, const UA_String name) {
+ /* Check if the namespace already exists in the server's namespace array */
+ for(UA_UInt16 i = 0; i < server->namespacesSize; ++i) {
+ if(UA_String_equal(&name, &server->namespaces[i]))
+ return i;
+ }
+
+ /* Make the array bigger */
+ UA_String *newNS = (UA_String*)UA_realloc(server->namespaces,
+ sizeof(UA_String) * (server->namespacesSize + 1));
+ if(!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;
+
+ /* Announce the change (otherwise, the array appears unchanged) */
+ ++server->namespacesSize;
+ return (UA_UInt16)(server->namespacesSize - 1);
+}
+
+UA_UInt16 UA_Server_addNamespace(UA_Server *server, const char* name) {
+ /* Override const attribute to get string (dirty hack) */
+ UA_String nameString;
+ nameString.length = strlen(name);
+ nameString.data = (UA_Byte*)(uintptr_t)name;
+ return addNamespace(server, nameString);
+}
+
+UA_StatusCode
+UA_Server_forEachChildNodeCall(UA_Server *server, UA_NodeId parentNodeId,
+ UA_NodeIteratorCallback callback, void *handle) {
+ const UA_Node *parent =
+ server->config.nodestore.getNode(server->config.nodestore.context,
+ &parentNodeId);
+ if(!parent)
+ return UA_STATUSCODE_BADNODEIDINVALID;
+
+ /* 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) {
+ server->config.nodestore.releaseNode(server->config.nodestore.context, parent);
+ return UA_STATUSCODE_BADUNEXPECTEDERROR;
+ }
+
+ 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->targetIdsSize; j++)
+ retval |= callback(ref->targetIds[j].nodeId, ref->isInverse,
+ ref->referenceTypeId, handle);
+ }
+ UA_Node_deleteMembers(parentCopy);
+ UA_free(parentCopy);
+
+ server->config.nodestore.releaseNode(server->config.nodestore.context, parent);
+ return retval;
+}
+
+/********************/
+/* Server Lifecycle */
+/********************/
+
+/* The server needs to be stopped before it can be deleted */
+void UA_Server_delete(UA_Server *server) {
+ /* Delete all internal data */
+ UA_SecureChannelManager_deleteMembers(&server->secureChannelManager);
+ UA_SessionManager_deleteMembers(&server->sessionManager);
+ UA_Array_delete(server->namespaces, server->namespacesSize, &UA_TYPES[UA_TYPES_STRING]);
+
+#ifdef UA_ENABLE_DISCOVERY
+ registeredServer_list_entry *rs, *rs_tmp;
+ LIST_FOREACH_SAFE(rs, &server->registeredServers, pointers, rs_tmp) {
+ LIST_REMOVE(rs, pointers);
+ UA_RegisteredServer_deleteMembers(&rs->registeredServer);
+ UA_free(rs);
+ }
+ periodicServerRegisterCallback_entry *ps, *ps_tmp;
+ LIST_FOREACH_SAFE(ps, &server->periodicServerRegisterCallbacks, pointers, ps_tmp) {
+ LIST_REMOVE(ps, pointers);
+ UA_free(ps->callback);
+ UA_free(ps);
+ }
+
+# ifdef UA_ENABLE_DISCOVERY_MULTICAST
+ if(server->config.applicationDescription.applicationType == UA_APPLICATIONTYPE_DISCOVERYSERVER)
+ destroyMulticastDiscoveryServer(server);
+
+ serverOnNetwork_list_entry *son, *son_tmp;
+ LIST_FOREACH_SAFE(son, &server->serverOnNetwork, pointers, son_tmp) {
+ LIST_REMOVE(son, pointers);
+ UA_ServerOnNetwork_deleteMembers(&son->serverOnNetwork);
+ if(son->pathTmp)
+ UA_free(son->pathTmp);
+ UA_free(son);
+ }
+
+ for(size_t i = 0; i < SERVER_ON_NETWORK_HASH_PRIME; i++) {
+ serverOnNetwork_hash_entry* currHash = server->serverOnNetworkHash[i];
+ while(currHash) {
+ serverOnNetwork_hash_entry* nextHash = currHash->next;
+ UA_free(currHash);
+ currHash = nextHash;
+ }
+ }
+# endif
+
+#endif
+
+ /* Clean up the admin session */
+ UA_Session_deleteMembersCleanup(&server->adminSession, server);
+
+#ifdef UA_ENABLE_MULTITHREADING
+ /* Process new delayed callbacks from the cleanup */
+ UA_Server_cleanupDispatchQueue(server);
+ pthread_mutex_destroy(&server->dispatchQueue_accessMutex);
+ pthread_cond_destroy(&server->dispatchQueue_condition);
+ pthread_mutex_destroy(&server->dispatchQueue_conditionMutex);
+#else
+ /* Process new delayed callbacks from the cleanup */
+ UA_Server_cleanupDelayedCallbacks(server);
+#endif
+
+ /* Delete the timed work */
+ UA_Timer_deleteMembers(&server->timer);
+
+ /* Delete the server itself */
+ UA_free(server);
+}
+
+/* Recurring cleanup. Removing unused and timed-out channels and sessions */
+static void
+UA_Server_cleanup(UA_Server *server, void *_) {
+ UA_DateTime nowMonotonic = UA_DateTime_nowMonotonic();
+ UA_SessionManager_cleanupTimedOut(&server->sessionManager, nowMonotonic);
+ UA_SecureChannelManager_cleanupTimedOut(&server->secureChannelManager, nowMonotonic);
+#ifdef UA_ENABLE_DISCOVERY
+ UA_Discovery_cleanupTimedOut(server, nowMonotonic);
+#endif
+}
+
+/********************/
+/* Server Lifecycle */
+/********************/
+
+UA_Server *
+UA_Server_new(const UA_ServerConfig *config) {
+ /* A config is required */
+ if(!config)
+ return NULL;
+
+ /* At least one endpoint has to be configured */
+ if(config->endpointsSize == 0) {
+ UA_LOG_FATAL(config->logger, UA_LOGCATEGORY_SERVER,
+ "There has to be at least one endpoint.");
+ return NULL;
+ }
+
+ /* Allocate the server */
+ UA_Server *server = (UA_Server *)UA_calloc(1, sizeof(UA_Server));
+ if(!server)
+ return NULL;
+
+ /* Set the config */
+ server->config = *config;
+
+ /* Initialize the admin session */
+ UA_Session_init(&server->adminSession);
+ server->adminSession.header.authenticationToken = UA_NODEID_NUMERIC(0, 1);
+ server->adminSession.sessionId.identifierType = UA_NODEIDTYPE_GUID;
+ server->adminSession.sessionId.identifier.guid.data1 = 1;
+ server->adminSession.sessionName = UA_STRING_ALLOC("Administrator Session");
+ server->adminSession.validTill = UA_INT64_MAX;
+ server->adminSession.availableContinuationPoints = UA_MAXCONTINUATIONPOINTS;
+
+ /* Init start time to zero, the actual start time will be sampled in
+ * UA_Server_run_startup() */
+ server->startTime = 0;
+
+ /* Set a seed for non-cyptographic randomness */
+#ifndef UA_ENABLE_DETERMINISTIC_RNG
+ UA_random_seed((UA_UInt64)UA_DateTime_now());
+#endif
+
+ /* Initialize the handling of repeated callbacks */
+ UA_Timer_init(&server->timer);
+
+ /* Initialized the linked list for delayed callbacks */
+#ifndef UA_ENABLE_MULTITHREADING
+ SLIST_INIT(&server->delayedCallbacks);
+#endif
+
+ /* Initialized the dispatch queue for worker threads */
+#ifdef UA_ENABLE_MULTITHREADING
+ SIMPLEQ_INIT(&server->dispatchQueue);
+#endif
+
+ /* Create Namespaces 0 and 1 */
+ server->namespaces = (UA_String *)UA_Array_new(2, &UA_TYPES[UA_TYPES_STRING]);
+ server->namespaces[0] = UA_STRING_ALLOC("http://opcfoundation.org/UA/");
+ UA_String_copy(&server->config.applicationDescription.applicationUri, &server->namespaces[1]);
+ server->namespacesSize = 2;
+
+ /* Initialized SecureChannel and Session managers */
+ UA_SecureChannelManager_init(&server->secureChannelManager, server);
+ UA_SessionManager_init(&server->sessionManager, server);
+
+ /* Add a regular callback for cleanup and maintenance */
+ UA_Server_addRepeatedCallback(server, (UA_ServerCallback)UA_Server_cleanup, NULL,
+ 10000, NULL);
+
+ /* Initialized discovery database */
+#ifdef UA_ENABLE_DISCOVERY
+ LIST_INIT(&server->registeredServers);
+ server->registeredServersSize = 0;
+ LIST_INIT(&server->periodicServerRegisterCallbacks);
+ server->registerServerCallback = NULL;
+ server->registerServerCallbackData = NULL;
+#endif
+
+ /* Initialize multicast discovery */
+#if defined(UA_ENABLE_DISCOVERY) && defined(UA_ENABLE_DISCOVERY_MULTICAST)
+ server->mdnsDaemon = NULL;
+#ifdef _WIN32
+ server->mdnsSocket = INVALID_SOCKET;
+#else
+ server->mdnsSocket = -1;
+#endif
+ server->mdnsMainSrvAdded = UA_FALSE;
+ if(server->config.applicationDescription.applicationType == UA_APPLICATIONTYPE_DISCOVERYSERVER)
+ initMulticastDiscoveryServer(server);
+
+ LIST_INIT(&server->serverOnNetwork);
+ server->serverOnNetworkSize = 0;
+ server->serverOnNetworkRecordIdCounter = 0;
+ server->serverOnNetworkRecordIdLastReset = UA_DateTime_now();
+ memset(server->serverOnNetworkHash, 0,
+ sizeof(struct serverOnNetwork_hash_entry*) * SERVER_ON_NETWORK_HASH_PRIME);
+
+ server->serverOnNetworkCallback = NULL;
+ server->serverOnNetworkCallbackData = NULL;
+#endif
+
+ /* Initialize namespace 0*/
+ UA_StatusCode retVal = UA_Server_initNS0(server);
+ if(retVal != UA_STATUSCODE_GOOD) {
+ UA_LOG_ERROR(config->logger, UA_LOGCATEGORY_SERVER,
+ "Initialization of Namespace 0 failed with %s. "
+ "See previous outputs for any error messages.",
+ UA_StatusCode_name(retVal));
+ UA_Server_delete(server);
+ return NULL;
+ }
+
+ return server;
+}
+
+/*****************/
+/* Repeated Jobs */
+/*****************/
+
+UA_StatusCode
+UA_Server_addRepeatedCallback(UA_Server *server, UA_ServerCallback callback,
+ void *data, UA_UInt32 interval,
+ UA_UInt64 *callbackId) {
+ return UA_Timer_addRepeatedCallback(&server->timer, (UA_TimerCallback)callback,
+ data, interval, callbackId);
+}
+
+UA_StatusCode
+UA_Server_changeRepeatedCallbackInterval(UA_Server *server, UA_UInt64 callbackId,
+ UA_UInt32 interval) {
+ return UA_Timer_changeRepeatedCallbackInterval(&server->timer, callbackId, interval);
+}
+
+UA_StatusCode
+UA_Server_removeRepeatedCallback(UA_Server *server, UA_UInt64 callbackId) {
+ return UA_Timer_removeRepeatedCallback(&server->timer, callbackId);
+}
+
+/*********************************** amalgamated original file "/home/jvoe/open62541/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) Julius Pfrommer, Fraunhofer IOSB
+ * Copyright 2017 (c) Stefan Profanter, fortiss GmbH
+ * Copyright 2017 (c) Thomas Bender
+ * Copyright 2017 (c) Julian Grothoff
+ * Copyright 2017 (c) Henrik Norrman
+ */
+
+
+/*****************/
+/* Node Creation */
+/*****************/
+
+static UA_StatusCode
+addNode_begin(UA_Server *server, UA_NodeClass nodeClass,
+ UA_UInt32 nodeId, char *name, void *attributes,
+ const UA_DataType *attributesType) {
+ UA_AddNodesItem item;
+ UA_AddNodesItem_init(&item);
+ 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_NodeId parentNode = UA_NODEID_NULL;
+ UA_NodeId referenceType = UA_NODEID_NULL;
+ return Operation_addNode_begin(server, &server->adminSession, NULL, &item,
+ &parentNode, &referenceType, NULL);
+}
+
+static UA_StatusCode
+addNode_finish(UA_Server *server, UA_UInt32 nodeId,
+ UA_UInt32 parentNodeId, UA_UInt32 referenceTypeId) {
+ UA_NodeId sourceId = UA_NODEID_NUMERIC(0, nodeId);
+ UA_NodeId refTypeId = UA_NODEID_NUMERIC(0, referenceTypeId);
+ UA_ExpandedNodeId targetId = UA_EXPANDEDNODEID_NUMERIC(0, parentNodeId);
+ UA_StatusCode retval = UA_Server_addReference(server, sourceId, refTypeId, targetId, UA_FALSE);
+ if (retval != UA_STATUSCODE_GOOD)
+ return retval;
+
+
+ UA_NodeId node = UA_NODEID_NUMERIC(0, nodeId);
+ return Operation_addNode_finish(server, &server->adminSession, &node);
+}
+
+static UA_StatusCode
+addDataTypeNode(UA_Server *server, char* name, UA_UInt32 datatypeid,
+ UA_Boolean isAbstract, UA_UInt32 parentid) {
+ UA_DataTypeAttributes attr = UA_DataTypeAttributes_default;
+ attr.displayName = UA_LOCALIZEDTEXT("", name);
+ attr.isAbstract = isAbstract;
+ return UA_Server_addDataTypeNode(server, UA_NODEID_NUMERIC(0, datatypeid),
+ UA_NODEID_NUMERIC(0, parentid), UA_NODEID_NULL,
+ UA_QUALIFIEDNAME(0, name), attr, NULL, NULL);
+}
+
+static UA_StatusCode
+addObjectTypeNode(UA_Server *server, char* name, UA_UInt32 objecttypeid,
+ UA_Boolean isAbstract, UA_UInt32 parentid) {
+ UA_ObjectTypeAttributes attr = UA_ObjectTypeAttributes_default;
+ attr.displayName = UA_LOCALIZEDTEXT("", name);
+ attr.isAbstract = isAbstract;
+ return UA_Server_addObjectTypeNode(server, UA_NODEID_NUMERIC(0, objecttypeid),
+ UA_NODEID_NUMERIC(0, parentid), UA_NODEID_NULL,
+ UA_QUALIFIEDNAME(0, name), attr, NULL, NULL);
+}
+
+static UA_StatusCode
+addObjectNode(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
+addReferenceTypeNode(UA_Server *server, char* name, char *inverseName, UA_UInt32 referencetypeid,
+ UA_Boolean isabstract, UA_Boolean symmetric, UA_UInt32 parentid) {
+ UA_ReferenceTypeAttributes reference_attr = UA_ReferenceTypeAttributes_default;
+ reference_attr.displayName = UA_LOCALIZEDTEXT("", name);
+ reference_attr.isAbstract = isabstract;
+ reference_attr.symmetric = symmetric;
+ if(inverseName)
+ reference_attr.inverseName = UA_LOCALIZEDTEXT("", inverseName);
+ return UA_Server_addReferenceTypeNode(server, UA_NODEID_NUMERIC(0, referencetypeid),
+ UA_NODEID_NUMERIC(0, parentid), UA_NODEID_NULL,
+ UA_QUALIFIEDNAME(0, name), reference_attr, NULL, NULL);
+}
+
+static UA_StatusCode
+addVariableTypeNode(UA_Server *server, char* name, UA_UInt32 variabletypeid,
+ UA_Boolean isAbstract, UA_Int32 valueRank, UA_UInt32 dataType,
+ const UA_DataType *type, UA_UInt32 parentid) {
+ UA_VariableTypeAttributes attr = UA_VariableTypeAttributes_default;
+ attr.displayName = UA_LOCALIZEDTEXT("", name);
+ attr.dataType = UA_NODEID_NUMERIC(0, dataType);
+ attr.isAbstract = isAbstract;
+ attr.valueRank = valueRank;
+
+ if(type) {
+ UA_STACKARRAY(UA_Byte, tempVal, type->memSize);
+ UA_init(tempVal, type);
+ UA_Variant_setScalar(&attr.value, tempVal, type);
+ return UA_Server_addVariableTypeNode(server, UA_NODEID_NUMERIC(0, variabletypeid),
+ UA_NODEID_NUMERIC(0, parentid), UA_NODEID_NULL,
+ UA_QUALIFIEDNAME(0, name), UA_NODEID_NULL, attr, NULL, NULL);
+ }
+ return UA_Server_addVariableTypeNode(server, UA_NODEID_NUMERIC(0, variabletypeid),
+ UA_NODEID_NUMERIC(0, parentid), UA_NODEID_NULL,
+ UA_QUALIFIEDNAME(0, name), UA_NODEID_NULL, attr, NULL, NULL);
+}
+
+/**********************/
+/* Create Namespace 0 */
+/**********************/
+
+/* Creates the basic nodes which are expected by the nodeset compiler to be
+ * already created. This is necessary to reduce the dependencies for the nodeset
+ * compiler. */
+static UA_StatusCode
+UA_Server_createNS0_base(UA_Server *server) {
+
+ UA_StatusCode ret = UA_STATUSCODE_GOOD;
+ /*********************************/
+ /* Bootstrap reference hierarchy */
+ /*********************************/
+
+ /* Bootstrap References and HasSubtype */
+ UA_ReferenceTypeAttributes references_attr = UA_ReferenceTypeAttributes_default;
+ references_attr.displayName = UA_LOCALIZEDTEXT("", "References");
+ references_attr.isAbstract = true;
+ references_attr.symmetric = true;
+ references_attr.inverseName = UA_LOCALIZEDTEXT("", "References");
+ ret |= addNode_begin(server, UA_NODECLASS_REFERENCETYPE, UA_NS0ID_REFERENCES, "References",
+ &references_attr, &UA_TYPES[UA_TYPES_REFERENCETYPEATTRIBUTES]);
+
+ UA_ReferenceTypeAttributes hassubtype_attr = UA_ReferenceTypeAttributes_default;
+ hassubtype_attr.displayName = UA_LOCALIZEDTEXT("", "HasSubtype");
+ hassubtype_attr.isAbstract = false;
+ hassubtype_attr.symmetric = false;
+ hassubtype_attr.inverseName = UA_LOCALIZEDTEXT("", "HasSupertype");
+ ret |= addNode_begin(server, UA_NODECLASS_REFERENCETYPE, UA_NS0ID_HASSUBTYPE, "HasSubtype",
+ &hassubtype_attr, &UA_TYPES[UA_TYPES_REFERENCETYPEATTRIBUTES]);
+
+ ret |= addReferenceTypeNode(server, "HierarchicalReferences", NULL,
+ UA_NS0ID_HIERARCHICALREFERENCES,
+ true, false, UA_NS0ID_REFERENCES);
+
+ ret |= addReferenceTypeNode(server, "NonHierarchicalReferences", NULL,
+ UA_NS0ID_NONHIERARCHICALREFERENCES,
+ true, false, UA_NS0ID_REFERENCES);
+
+ ret |= addReferenceTypeNode(server, "HasChild", NULL, UA_NS0ID_HASCHILD,
+ true, false, UA_NS0ID_HIERARCHICALREFERENCES);
+
+ ret |= addReferenceTypeNode(server, "Organizes", "OrganizedBy", UA_NS0ID_ORGANIZES,
+ false, false, UA_NS0ID_HIERARCHICALREFERENCES);
+
+ ret |= addReferenceTypeNode(server, "HasEventSource", "EventSourceOf", UA_NS0ID_HASEVENTSOURCE,
+ false, false, UA_NS0ID_HIERARCHICALREFERENCES);
+
+ ret |= addReferenceTypeNode(server, "HasModellingRule", "ModellingRuleOf", UA_NS0ID_HASMODELLINGRULE,
+ false, false, UA_NS0ID_NONHIERARCHICALREFERENCES);
+
+ ret |= addReferenceTypeNode(server, "HasEncoding", "EncodingOf", UA_NS0ID_HASENCODING,
+ false, false, UA_NS0ID_NONHIERARCHICALREFERENCES);
+
+ ret |= addReferenceTypeNode(server, "HasDescription", "DescriptionOf", UA_NS0ID_HASDESCRIPTION,
+ false, false, UA_NS0ID_NONHIERARCHICALREFERENCES);
+
+ ret |= addReferenceTypeNode(server, "HasTypeDefinition", "TypeDefinitionOf", UA_NS0ID_HASTYPEDEFINITION,
+ false, false, UA_NS0ID_NONHIERARCHICALREFERENCES);
+
+ ret |= addReferenceTypeNode(server, "GeneratesEvent", "GeneratedBy", UA_NS0ID_GENERATESEVENT,
+ false, false, UA_NS0ID_NONHIERARCHICALREFERENCES);
+
+ ret |= addReferenceTypeNode(server, "Aggregates", "AggregatedBy", UA_NS0ID_AGGREGATES,
+ false, false, UA_NS0ID_HASCHILD);
+
+ /* Complete bootstrap of HasSubtype */
+ ret |= addNode_finish(server, UA_NS0ID_HASSUBTYPE, UA_NS0ID_HASCHILD, UA_NS0ID_HASSUBTYPE);
+
+ ret |= addReferenceTypeNode(server, "HasProperty", "PropertyOf", UA_NS0ID_HASPROPERTY,
+ false, false, UA_NS0ID_AGGREGATES);
+
+ ret |= addReferenceTypeNode(server, "HasComponent", "ComponentOf", UA_NS0ID_HASCOMPONENT,
+ false, false, UA_NS0ID_AGGREGATES);
+
+ ret |= addReferenceTypeNode(server, "HasNotifier", "NotifierOf", UA_NS0ID_HASNOTIFIER,
+ false, false, UA_NS0ID_HASEVENTSOURCE);
+
+ ret |= addReferenceTypeNode(server, "HasOrderedComponent", "OrderedComponentOf",
+ UA_NS0ID_HASORDEREDCOMPONENT, false, false, UA_NS0ID_HASCOMPONENT);
+
+ /**************/
+ /* Data Types */
+ /**************/
+
+ /* Bootstrap BaseDataType */
+ UA_DataTypeAttributes basedatatype_attr = UA_DataTypeAttributes_default;
+ basedatatype_attr.displayName = UA_LOCALIZEDTEXT("", "BaseDataType");
+ basedatatype_attr.isAbstract = true;
+ ret |= addNode_begin(server, UA_NODECLASS_DATATYPE, UA_NS0ID_BASEDATATYPE, "BaseDataType",
+ &basedatatype_attr, &UA_TYPES[UA_TYPES_DATATYPEATTRIBUTES]);
+
+ ret |= addDataTypeNode(server, "Number", UA_NS0ID_NUMBER, true, UA_NS0ID_BASEDATATYPE);
+ ret |= addDataTypeNode(server, "Integer", UA_NS0ID_INTEGER, true, UA_NS0ID_NUMBER);
+ ret |= addDataTypeNode(server, "UInteger", UA_NS0ID_UINTEGER, true, UA_NS0ID_NUMBER);
+ ret |= addDataTypeNode(server, "Boolean", UA_NS0ID_BOOLEAN, false, UA_NS0ID_BASEDATATYPE);
+ ret |= addDataTypeNode(server, "SByte", UA_NS0ID_SBYTE, false, UA_NS0ID_INTEGER);
+ ret |= addDataTypeNode(server, "Byte", UA_NS0ID_BYTE, false, UA_NS0ID_UINTEGER);
+ ret |= addDataTypeNode(server, "Int16", UA_NS0ID_INT16, false, UA_NS0ID_INTEGER);
+ ret |= addDataTypeNode(server, "UInt16", UA_NS0ID_UINT16, false, UA_NS0ID_UINTEGER);
+ ret |= addDataTypeNode(server, "Int32", UA_NS0ID_INT32, false, UA_NS0ID_INTEGER);
+ ret |= addDataTypeNode(server, "UInt32", UA_NS0ID_UINT32, false, UA_NS0ID_UINTEGER);
+ ret |= addDataTypeNode(server, "Int64", UA_NS0ID_INT64, false, UA_NS0ID_INTEGER);
+ ret |= addDataTypeNode(server, "UInt64", UA_NS0ID_UINT64, false, UA_NS0ID_UINTEGER);
+ ret |= addDataTypeNode(server, "Float", UA_NS0ID_FLOAT, false, UA_NS0ID_NUMBER);
+ ret |= addDataTypeNode(server, "Double", UA_NS0ID_DOUBLE, false, UA_NS0ID_NUMBER);
+ ret |= addDataTypeNode(server, "DateTime", UA_NS0ID_DATETIME, false, UA_NS0ID_BASEDATATYPE);
+ ret |= addDataTypeNode(server, "String", UA_NS0ID_STRING, false, UA_NS0ID_BASEDATATYPE);
+ ret |= addDataTypeNode(server, "ByteString", UA_NS0ID_BYTESTRING, false, UA_NS0ID_BASEDATATYPE);
+ ret |= addDataTypeNode(server, "Guid", UA_NS0ID_GUID, false, UA_NS0ID_BASEDATATYPE);
+ ret |= addDataTypeNode(server, "XmlElement", UA_NS0ID_XMLELEMENT, false, UA_NS0ID_BASEDATATYPE);
+ ret |= addDataTypeNode(server, "NodeId", UA_NS0ID_NODEID, false, UA_NS0ID_BASEDATATYPE);
+ ret |= addDataTypeNode(server, "ExpandedNodeId", UA_NS0ID_EXPANDEDNODEID, false, UA_NS0ID_BASEDATATYPE);
+ ret |= addDataTypeNode(server, "QualifiedName", UA_NS0ID_QUALIFIEDNAME, false, UA_NS0ID_BASEDATATYPE);
+ ret |= addDataTypeNode(server, "LocalizedText", UA_NS0ID_LOCALIZEDTEXT, false, UA_NS0ID_BASEDATATYPE);
+ ret |= addDataTypeNode(server, "StatusCode", UA_NS0ID_STATUSCODE, false, UA_NS0ID_BASEDATATYPE);
+ ret |= addDataTypeNode(server, "Structure", UA_NS0ID_STRUCTURE, true, UA_NS0ID_BASEDATATYPE);
+ ret |= addDataTypeNode(server, "Decimal128", UA_NS0ID_DECIMAL128, false, UA_NS0ID_NUMBER);
+
+ ret |= addDataTypeNode(server, "Duration", UA_NS0ID_DURATION, false, UA_NS0ID_DOUBLE);
+ ret |= addDataTypeNode(server, "UtcTime", UA_NS0ID_UTCTIME, false, UA_NS0ID_DATETIME);
+ ret |= addDataTypeNode(server, "LocaleId", UA_NS0ID_LOCALEID, false, UA_NS0ID_STRING);
+
+ /*****************/
+ /* VariableTypes */
+ /*****************/
+
+ /* Bootstrap BaseVariableType */
+ UA_VariableTypeAttributes basevar_attr = UA_VariableTypeAttributes_default;
+ basevar_attr.displayName = UA_LOCALIZEDTEXT("", "BaseVariableType");
+ basevar_attr.isAbstract = true;
+ basevar_attr.valueRank = UA_VALUERANK_ANY;
+ basevar_attr.dataType = UA_NODEID_NUMERIC(0, UA_NS0ID_BASEDATATYPE);
+ ret |= addNode_begin(server, UA_NODECLASS_VARIABLETYPE, UA_NS0ID_BASEVARIABLETYPE, "BaseVariableType",
+ &basevar_attr, &UA_TYPES[UA_TYPES_VARIABLETYPEATTRIBUTES]);
+
+ ret |= addVariableTypeNode(server, "BaseDataVariableType", UA_NS0ID_BASEDATAVARIABLETYPE,
+ false, -2, UA_NS0ID_BASEDATATYPE, NULL, UA_NS0ID_BASEVARIABLETYPE);
+
+ /***************/
+ /* ObjectTypes */
+ /***************/
+
+ /* Bootstrap BaseObjectType */
+ UA_ObjectTypeAttributes baseobj_attr = UA_ObjectTypeAttributes_default;
+ baseobj_attr.displayName = UA_LOCALIZEDTEXT("", "BaseObjectType");
+ ret |= addNode_begin(server, UA_NODECLASS_OBJECTTYPE, UA_NS0ID_BASEOBJECTTYPE, "BaseObjectType",
+ &baseobj_attr, &UA_TYPES[UA_TYPES_OBJECTTYPEATTRIBUTES]);
+
+ ret |= addObjectTypeNode(server, "FolderType", UA_NS0ID_FOLDERTYPE,
+ false, UA_NS0ID_BASEOBJECTTYPE);
+
+ /******************/
+ /* Root and below */
+ /******************/
+
+ ret |= addObjectNode(server, "Root", UA_NS0ID_ROOTFOLDER, 0, 0, UA_NS0ID_FOLDERTYPE);
+
+ ret |= addObjectNode(server, "Objects", UA_NS0ID_OBJECTSFOLDER, UA_NS0ID_ROOTFOLDER,
+ UA_NS0ID_ORGANIZES, UA_NS0ID_FOLDERTYPE);
+
+ ret |= addObjectNode(server, "Types", UA_NS0ID_TYPESFOLDER, UA_NS0ID_ROOTFOLDER,
+ UA_NS0ID_ORGANIZES, UA_NS0ID_FOLDERTYPE);
+
+ ret |= addObjectNode(server, "ReferenceTypes", UA_NS0ID_REFERENCETYPESFOLDER, UA_NS0ID_TYPESFOLDER,
+ UA_NS0ID_ORGANIZES, UA_NS0ID_FOLDERTYPE);
+ ret |= addNode_finish(server, UA_NS0ID_REFERENCES, UA_NS0ID_REFERENCETYPESFOLDER,
+ UA_NS0ID_ORGANIZES);
+
+ ret |= addObjectNode(server, "DataTypes", UA_NS0ID_DATATYPESFOLDER, UA_NS0ID_TYPESFOLDER,
+ UA_NS0ID_ORGANIZES, UA_NS0ID_FOLDERTYPE);
+
+ ret |= addNode_finish(server, UA_NS0ID_BASEDATATYPE, UA_NS0ID_DATATYPESFOLDER,
+ UA_NS0ID_ORGANIZES);
+
+ ret |= addObjectNode(server, "VariableTypes", UA_NS0ID_VARIABLETYPESFOLDER, UA_NS0ID_TYPESFOLDER,
+ UA_NS0ID_ORGANIZES, UA_NS0ID_FOLDERTYPE);
+
+ ret |= addNode_finish(server, UA_NS0ID_BASEVARIABLETYPE, UA_NS0ID_VARIABLETYPESFOLDER,
+ UA_NS0ID_ORGANIZES);
+
+ ret |= addObjectNode(server, "ObjectTypes", UA_NS0ID_OBJECTTYPESFOLDER, UA_NS0ID_TYPESFOLDER,
+ UA_NS0ID_ORGANIZES, UA_NS0ID_FOLDERTYPE);
+ ret |= addNode_finish(server, UA_NS0ID_BASEOBJECTTYPE, UA_NS0ID_OBJECTTYPESFOLDER,
+ UA_NS0ID_ORGANIZES);
+
+ ret |= addObjectNode(server, "EventTypes", UA_NS0ID_EVENTTYPESFOLDER, UA_NS0ID_TYPESFOLDER,
+ UA_NS0ID_ORGANIZES, UA_NS0ID_FOLDERTYPE);
+
+ ret |= addObjectNode(server, "Views", UA_NS0ID_VIEWSFOLDER, UA_NS0ID_ROOTFOLDER,
+ UA_NS0ID_ORGANIZES, UA_NS0ID_FOLDERTYPE);
+
+ if(ret != UA_STATUSCODE_GOOD)
+ return UA_STATUSCODE_BADINTERNALERROR;
+ return UA_STATUSCODE_GOOD;
+}
+
+/****************/
+/* Data Sources */
+/****************/
+
+static UA_StatusCode
+readStatus(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;
+ }
+
+ UA_ServerStatusDataType *statustype = UA_ServerStatusDataType_new();
+ statustype->startTime = server->startTime;
+ statustype->currentTime = UA_DateTime_now();
+ statustype->state = UA_SERVERSTATE_RUNNING;
+ statustype->secondsTillShutdown = 0;
+ UA_BuildInfo_copy(&server->config.buildInfo, &statustype->buildInfo);
+
+ value->value.type = &UA_TYPES[UA_TYPES_SERVERSTATUSDATATYPE];
+ value->value.arrayLength = 0;
+ value->value.data = statustype;
+ value->value.arrayDimensionsSize = 0;
+ value->value.arrayDimensions = NULL;
+ value->hasValue = true;
+ if(sourceTimestamp) {
+ value->hasSourceTimestamp = true;
+ value->sourceTimestamp = UA_DateTime_now();
+ }
+ return UA_STATUSCODE_GOOD;
+}
+
+static UA_StatusCode
+readServiceLevel(UA_Server *server, const UA_NodeId *sessionId, void *sessionContext,
+ const UA_NodeId *nodeId, void *nodeContext, UA_Boolean includeSourceTimeStamp,
+ const UA_NumericRange *range, UA_DataValue *value) {
+ if(range) {
+ value->hasStatus = true;
+ value->status = UA_STATUSCODE_BADINDEXRANGEINVALID;
+ return UA_STATUSCODE_GOOD;
+ }
+
+ value->value.type = &UA_TYPES[UA_TYPES_BYTE];
+ value->value.arrayLength = 0;
+ UA_Byte *byte = UA_Byte_new();
+ *byte = 255;
+ value->value.data = byte;
+ value->value.arrayDimensionsSize = 0;
+ value->value.arrayDimensions = NULL;
+ value->hasValue = true;
+ if(includeSourceTimeStamp) {
+ value->hasSourceTimestamp = true;
+ value->sourceTimestamp = UA_DateTime_now();
+ }
+ return UA_STATUSCODE_GOOD;
+}
+
+static UA_StatusCode
+readAuditing(UA_Server *server, const UA_NodeId *sessionId, void *sessionContext,
+ const UA_NodeId *nodeId, void *nodeContext, UA_Boolean includeSourceTimeStamp,
+ const UA_NumericRange *range, UA_DataValue *value) {
+ if(range) {
+ value->hasStatus = true;
+ value->status = UA_STATUSCODE_BADINDEXRANGEINVALID;
+ return UA_STATUSCODE_GOOD;
+ }
+
+ value->value.type = &UA_TYPES[UA_TYPES_BOOLEAN];
+ value->value.arrayLength = 0;
+ UA_Boolean *boolean = UA_Boolean_new();
+ *boolean = false;
+ value->value.data = boolean;
+ value->value.arrayDimensionsSize = 0;
+ value->value.arrayDimensions = NULL;
+ value->hasValue = true;
+ if(includeSourceTimeStamp) {
+ value->hasSourceTimestamp = true;
+ value->sourceTimestamp = UA_DateTime_now();
+ }
+ return UA_STATUSCODE_GOOD;
+}
+
+static UA_StatusCode
+readNamespaces(UA_Server *server, const UA_NodeId *sessionId, void *sessionContext,
+ const UA_NodeId *nodeid, void *nodeContext, UA_Boolean includeSourceTimeStamp,
+ const UA_NumericRange *range,
+ UA_DataValue *value) {
+ if(range) {
+ value->hasStatus = true;
+ value->status = UA_STATUSCODE_BADINDEXRANGEINVALID;
+ return UA_STATUSCODE_GOOD;
+ }
+ UA_StatusCode retval;
+ retval = UA_Variant_setArrayCopy(&value->value, server->namespaces,
+ server->namespacesSize, &UA_TYPES[UA_TYPES_STRING]);
+ if(retval != UA_STATUSCODE_GOOD)
+ return retval;
+ value->hasValue = true;
+ if(includeSourceTimeStamp) {
+ value->hasSourceTimestamp = true;
+ value->sourceTimestamp = UA_DateTime_now();
+ }
+ return UA_STATUSCODE_GOOD;
+}
+
+static UA_StatusCode
+writeNamespaces(UA_Server *server, const UA_NodeId *sessionId, void *sessionContext,
+ const UA_NodeId *nodeid, void *nodeContext, const UA_NumericRange *range,
+ const UA_DataValue *value) {
+ /* Check the data type */
+ if(!value->hasValue ||
+ value->value.type != &UA_TYPES[UA_TYPES_STRING])
+ return UA_STATUSCODE_BADTYPEMISMATCH;
+
+ /* Check that the variant is not empty */
+ if(!value->value.data)
+ return UA_STATUSCODE_BADTYPEMISMATCH;
+
+ /* TODO: Writing with a range is not implemented */
+ if(range)
+ return UA_STATUSCODE_BADINTERNALERROR;
+
+ UA_String *newNamespaces = (UA_String*)value->value.data;
+ size_t newNamespacesSize = value->value.arrayLength;
+
+ /* Test if we append to the existing namespaces */
+ if(newNamespacesSize <= server->namespacesSize)
+ return UA_STATUSCODE_BADTYPEMISMATCH;
+
+ /* Test if the existing namespaces are unchanged */
+ for(size_t i = 0; i < server->namespacesSize; ++i) {
+ if(!UA_String_equal(&server->namespaces[i], &newNamespaces[i]))
+ return UA_STATUSCODE_BADINTERNALERROR;
+ }
+
+ /* Add namespaces */
+ for(size_t i = server->namespacesSize; i < newNamespacesSize; ++i)
+ addNamespace(server, newNamespaces[i]);
+ return UA_STATUSCODE_GOOD;
+}
+
+static UA_StatusCode
+readCurrentTime(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;
+ }
+ UA_DateTime currentTime = UA_DateTime_now();
+ UA_StatusCode retval = UA_Variant_setScalarCopy(&value->value, &currentTime,
+ &UA_TYPES[UA_TYPES_DATETIME]);
+ if(retval != UA_STATUSCODE_GOOD)
+ return retval;
+ value->hasValue = true;
+ if(sourceTimeStamp) {
+ value->hasSourceTimestamp = true;
+ value->sourceTimestamp = currentTime;
+ }
+ return UA_STATUSCODE_GOOD;
+}
+
+#if defined(UA_ENABLE_METHODCALLS) && defined(UA_ENABLE_SUBSCRIPTIONS)
+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_Session *session = UA_SessionManager_getSessionById(&server->sessionManager, sessionId);
+ if(!session)
+ return UA_STATUSCODE_BADINTERNALERROR;
+ if (inputSize == 0 || !input[0].data)
+ return UA_STATUSCODE_BADSUBSCRIPTIONIDINVALID;
+ UA_UInt32 subscriptionId = *((UA_UInt32*)(input[0].data));
+ UA_Subscription* subscription = UA_Session_getSubscriptionById(session, subscriptionId);
+ 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;
+ }
+ else
+ return UA_STATUSCODE_BADSUBSCRIPTIONIDINVALID;
+ }
+
+ UA_UInt32 sizeOfOutput = 0;
+ UA_MonitoredItem* monitoredItem;
+ LIST_FOREACH(monitoredItem, &subscription->monitoredItems, listEntry) {
+ ++sizeOfOutput;
+ }
+ if(sizeOfOutput==0)
+ 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]);
+ UA_UInt32 i = 0;
+ LIST_FOREACH(monitoredItem, &subscription->monitoredItems, listEntry) {
+ clientHandles[i] = monitoredItem->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]);
+ return UA_STATUSCODE_GOOD;
+}
+#endif /* defined(UA_ENABLE_METHODCALLS) && defined(UA_ENABLE_SUBSCRIPTIONS) */
+
+static UA_StatusCode
+writeNs0Variable(UA_Server *server, UA_UInt32 id, void *v, const UA_DataType *type) {
+ UA_Variant var;
+ UA_Variant_init(&var);
+ UA_Variant_setScalar(&var, v, type);
+ return UA_Server_writeValue(server, UA_NODEID_NUMERIC(0, id), var);
+}
+
+static UA_StatusCode
+writeNs0VariableArray(UA_Server *server, UA_UInt32 id, void *v,
+ size_t length, const UA_DataType *type) {
+ UA_Variant var;
+ UA_Variant_init(&var);
+ UA_Variant_setArray(&var, v, length, type);
+ return UA_Server_writeValue(server, UA_NODEID_NUMERIC(0, id), var);
+}
+
+/* Initialize the nodeset 0 by using the generated code of the nodeset compiler.
+ * This also initialized the data sources for various variables, such as for
+ * 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;
+
+ /* Load nodes and references generated from the XML ns0 definition */
+ server->bootstrapNS0 = true;
+ retVal = ua_namespace0(server);
+ server->bootstrapNS0 = false;
+ if(retVal != UA_STATUSCODE_GOOD)
+ return retVal;
+
+ /* NamespaceArray */
+ UA_DataSource namespaceDataSource = {readNamespaces, NULL};
+ retVal |= UA_Server_setVariableNode_dataSource(server,
+ UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_NAMESPACEARRAY),
+ namespaceDataSource);
+
+ /* ServerArray */
+ retVal |= writeNs0VariableArray(server, UA_NS0ID_SERVER_SERVERARRAY,
+ &server->config.applicationDescription.applicationUri,
+ 1, &UA_TYPES[UA_TYPES_STRING]);
+
+ /* LocaleIdArray */
+ UA_LocaleId locale_en = UA_STRING("en");
+ retVal |= writeNs0VariableArray(server, UA_NS0ID_SERVER_SERVERCAPABILITIES_LOCALEIDARRAY,
+ &locale_en, 1, &UA_TYPES[UA_TYPES_LOCALEID]);
+
+ /* MaxBrowseContinuationPoints */
+ UA_UInt16 maxBrowseContinuationPoints = UA_MAXCONTINUATIONPOINTS;
+ retVal |= writeNs0Variable(server, UA_NS0ID_SERVER_SERVERCAPABILITIES_MAXBROWSECONTINUATIONPOINTS,
+ &maxBrowseContinuationPoints, &UA_TYPES[UA_TYPES_UINT16]);
+
+ /* ServerProfileArray */
+ UA_String profileArray[4];
+ UA_UInt16 profileArraySize = 0;
+#define ADDPROFILEARRAY(x) profileArray[profileArraySize++] = UA_STRING_ALLOC(x)
+ ADDPROFILEARRAY("http://opcfoundation.org/UA-Profile/Server/NanoEmbeddedDevice");
+#ifdef UA_ENABLE_NODEMANAGEMENT
+ ADDPROFILEARRAY("http://opcfoundation.org/UA-Profile/Server/NodeManagement");
+#endif
+#ifdef UA_ENABLE_METHODCALLS
+ ADDPROFILEARRAY("http://opcfoundation.org/UA-Profile/Server/Methods");
+#endif
+#ifdef UA_ENABLE_SUBSCRIPTIONS
+ ADDPROFILEARRAY("http://opcfoundation.org/UA-Profile/Server/EmbeddedDataChangeSubscription");
+#endif
+
+ retVal |= writeNs0VariableArray(server, UA_NS0ID_SERVER_SERVERCAPABILITIES_SERVERPROFILEARRAY,
+ profileArray, profileArraySize, &UA_TYPES[UA_TYPES_STRING]);
+ for(int i=0; i<profileArraySize; i++) {
+ UA_String_deleteMembers(&profileArray[i]);
+ }
+
+ /* MaxQueryContinuationPoints */
+ UA_UInt16 maxQueryContinuationPoints = 0;
+ retVal |= writeNs0Variable(server, UA_NS0ID_SERVER_SERVERCAPABILITIES_MAXQUERYCONTINUATIONPOINTS,
+ &maxQueryContinuationPoints, &UA_TYPES[UA_TYPES_UINT16]);
+
+ /* MaxHistoryContinuationPoints */
+ UA_UInt16 maxHistoryContinuationPoints = 0;
+ retVal |= writeNs0Variable(server, UA_NS0ID_SERVER_SERVERCAPABILITIES_MAXHISTORYCONTINUATIONPOINTS,
+ &maxHistoryContinuationPoints, &UA_TYPES[UA_TYPES_UINT16]);
+
+ /* MinSupportedSampleRate */
+ retVal |= writeNs0Variable(server, UA_NS0ID_SERVER_SERVERCAPABILITIES_MINSUPPORTEDSAMPLERATE,
+ &server->config.samplingIntervalLimits.min, &UA_TYPES[UA_TYPES_DURATION]);
+
+ /* 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 */
+ UA_Boolean enabledFlag = false;
+ retVal |= writeNs0Variable(server, UA_NS0ID_SERVER_SERVERDIAGNOSTICS_ENABLEDFLAG,
+ &enabledFlag, &UA_TYPES[UA_TYPES_BOOLEAN]);
+
+ /* ServerStatus */
+ UA_DataSource serverStatus = {readStatus, NULL};
+ retVal |= UA_Server_setVariableNode_dataSource(server,
+ UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERSTATUS), serverStatus);
+
+ /* StartTime will be sampled in UA_Server_run_startup()*/
+
+ /* CurrentTime */
+ UA_DataSource currentTime = {readCurrentTime, NULL};
+ retVal |= UA_Server_setVariableNode_dataSource(server,
+ UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERSTATUS_CURRENTTIME), currentTime);
+
+ /* State */
+ UA_ServerState state = UA_SERVERSTATE_RUNNING;
+ retVal |= writeNs0Variable(server, UA_NS0ID_SERVER_SERVERSTATUS_STATE,
+ &state, &UA_TYPES[UA_TYPES_SERVERSTATE]);
+
+ /* BuildInfo */
+ retVal |= writeNs0Variable(server, UA_NS0ID_SERVER_SERVERSTATUS_BUILDINFO,
+ &server->config.buildInfo, &UA_TYPES[UA_TYPES_BUILDINFO]);
+
+ /* BuildInfo - ProductUri */
+ retVal |= writeNs0Variable(server, UA_NS0ID_SERVER_SERVERSTATUS_BUILDINFO_PRODUCTURI,
+ &server->config.buildInfo.productUri, &UA_TYPES[UA_TYPES_STRING]);
+
+ /* BuildInfo - ManufacturerName */
+ retVal |= writeNs0Variable(server, UA_NS0ID_SERVER_SERVERSTATUS_BUILDINFO_MANUFACTURERNAME,
+ &server->config.buildInfo.manufacturerName, &UA_TYPES[UA_TYPES_STRING]);
+
+ /* BuildInfo - ProductName */
+ retVal |= writeNs0Variable(server, UA_NS0ID_SERVER_SERVERSTATUS_BUILDINFO_PRODUCTNAME,
+ &server->config.buildInfo.productName, &UA_TYPES[UA_TYPES_STRING]);
+
+ /* BuildInfo - SoftwareVersion */
+ retVal |= writeNs0Variable(server, UA_NS0ID_SERVER_SERVERSTATUS_BUILDINFO_SOFTWAREVERSION,
+ &server->config.buildInfo.softwareVersion, &UA_TYPES[UA_TYPES_STRING]);
+
+ /* BuildInfo - BuildNumber */
+ retVal |= writeNs0Variable(server, UA_NS0ID_SERVER_SERVERSTATUS_BUILDINFO_BUILDNUMBER,
+ &server->config.buildInfo.buildNumber, &UA_TYPES[UA_TYPES_STRING]);
+
+ /* BuildInfo - BuildDate */
+ retVal |= writeNs0Variable(server, UA_NS0ID_SERVER_SERVERSTATUS_BUILDINFO_BUILDDATE,
+ &server->config.buildInfo.buildDate, &UA_TYPES[UA_TYPES_DATETIME]);
+
+ /* SecondsTillShutdown */
+ UA_UInt32 secondsTillShutdown = 0;
+ retVal |= writeNs0Variable(server, UA_NS0ID_SERVER_SERVERSTATUS_SECONDSTILLSHUTDOWN,
+ &secondsTillShutdown, &UA_TYPES[UA_TYPES_UINT32]);
+
+ /* ShutDownReason */
+ UA_LocalizedText shutdownReason;
+ UA_LocalizedText_init(&shutdownReason);
+ retVal |= writeNs0Variable(server, UA_NS0ID_SERVER_SERVERSTATUS_SHUTDOWNREASON,
+ &shutdownReason, &UA_TYPES[UA_TYPES_LOCALIZEDTEXT]);
+
+ /* ServiceLevel */
+ UA_DataSource serviceLevel = {readServiceLevel, NULL};
+ retVal |= UA_Server_setVariableNode_dataSource(server,
+ UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVICELEVEL), serviceLevel);
+
+ /* Auditing */
+ UA_DataSource auditing = {readAuditing, NULL};
+ retVal |= UA_Server_setVariableNode_dataSource(server,
+ UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_AUDITING), auditing);
+
+ /* NamespaceArray */
+ UA_DataSource nsarray_datasource = {readNamespaces, writeNamespaces};
+ retVal |= UA_Server_setVariableNode_dataSource(server,
+ UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_NAMESPACEARRAY), nsarray_datasource);
+
+ /* Redundancy Support */
+ UA_RedundancySupport redundancySupport = UA_REDUNDANCYSUPPORT_NONE;
+ retVal |= writeNs0Variable(server, UA_NS0ID_SERVER_SERVERREDUNDANCY_REDUNDANCYSUPPORT,
+ &redundancySupport, &UA_TYPES[UA_TYPES_REDUNDANCYSUPPORT]);
+
+ /* ServerCapabilities - OperationLimits - MaxNodesPerRead */
+ retVal |= writeNs0Variable(server, UA_NS0ID_SERVER_SERVERCAPABILITIES_OPERATIONLIMITS_MAXNODESPERREAD,
+ &server->config.maxNodesPerRead, &UA_TYPES[UA_TYPES_UINT32]);
+
+ /* ServerCapabilities - OperationLimits - maxNodesPerWrite */
+ retVal |= writeNs0Variable(server, UA_NS0ID_SERVER_SERVERCAPABILITIES_OPERATIONLIMITS_MAXNODESPERWRITE,
+ &server->config.maxNodesPerWrite, &UA_TYPES[UA_TYPES_UINT32]);
+
+ /* ServerCapabilities - OperationLimits - MaxNodesPerMethodCall */
+ retVal |= writeNs0Variable(server, UA_NS0ID_SERVER_SERVERCAPABILITIES_OPERATIONLIMITS_MAXNODESPERMETHODCALL,
+ &server->config.maxNodesPerMethodCall, &UA_TYPES[UA_TYPES_UINT32]);
+
+ /* ServerCapabilities - OperationLimits - MaxNodesPerBrowse */
+ retVal |= writeNs0Variable(server, UA_NS0ID_SERVER_SERVERCAPABILITIES_OPERATIONLIMITS_MAXNODESPERBROWSE,
+ &server->config.maxNodesPerBrowse, &UA_TYPES[UA_TYPES_UINT32]);
+
+ /* ServerCapabilities - OperationLimits - MaxNodesPerRegisterNodes */
+ retVal |= writeNs0Variable(server, UA_NS0ID_SERVER_SERVERCAPABILITIES_OPERATIONLIMITS_MAXNODESPERREGISTERNODES,
+ &server->config.maxNodesPerRegisterNodes, &UA_TYPES[UA_TYPES_UINT32]);
+
+ /* ServerCapabilities - OperationLimits - MaxNodesPerTranslateBrowsePathsToNodeIds */
+ retVal |= writeNs0Variable(server, UA_NS0ID_SERVER_SERVERCAPABILITIES_OPERATIONLIMITS_MAXNODESPERTRANSLATEBROWSEPATHSTONODEIDS,
+ &server->config.maxNodesPerTranslateBrowsePathsToNodeIds, &UA_TYPES[UA_TYPES_UINT32]);
+
+ /* ServerCapabilities - OperationLimits - MaxNodesPerNodeManagement */
+ retVal |= writeNs0Variable(server, UA_NS0ID_SERVER_SERVERCAPABILITIES_OPERATIONLIMITS_MAXNODESPERNODEMANAGEMENT,
+ &server->config.maxNodesPerNodeManagement, &UA_TYPES[UA_TYPES_UINT32]);
+
+ /* ServerCapabilities - OperationLimits - MaxMonitoredItemsPerCall */
+ retVal |= writeNs0Variable(server, UA_NS0ID_SERVER_SERVERCAPABILITIES_OPERATIONLIMITS_MAXMONITOREDITEMSPERCALL,
+ &server->config.maxMonitoredItemsPerCall, &UA_TYPES[UA_TYPES_UINT32]);
+
+#if defined(UA_ENABLE_METHODCALLS) && defined(UA_ENABLE_SUBSCRIPTIONS)
+ retVal |= UA_Server_setMethodNode_callback(server,
+ UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_GETMONITOREDITEMS), readMonitoredItems);
+#endif
+ return retVal;
+}
+
+/*********************************** amalgamated original file "/home/jvoe/open62541/build/src_generated/ua_namespace0.c" ***********************************/
+
+/* WARNING: This is a generated file.
+ * Any manual changes will be overwritten. */
+
+
+
+/* HasHistoricalConfiguration - ns=0;i=56 */
+
+static UA_StatusCode function_ua_namespace0_0_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");
+attr.description = UA_LOCALIZEDTEXT("", "The type for a reference to the historical configuration for a data variable.");
+attr.writeMask = 0;
+attr.userWriteMask = 0;
+retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_REFERENCETYPE,
+UA_NODEID_NUMERIC(ns[0], 56),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_QUALIFIEDNAME(ns[0], "HasHistoricalConfiguration"),
+UA_NODEID_NULL,
+(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_REFERENCETYPEATTRIBUTES],NULL, NULL);
+retVal |= UA_Server_addReference(server, UA_NODEID_NUMERIC(ns[0], 56), UA_NODEID_NUMERIC(ns[0], 45), UA_EXPANDEDNODEID_NUMERIC(ns[0], 44), false);
+return retVal;
+}
+
+static UA_StatusCode function_ua_namespace0_0_finish(UA_Server *server, UA_UInt16* ns) {
+
+return UA_Server_addNode_finish(server,
+UA_NODEID_NUMERIC(ns[0], 56)
+);
+}
+
+/* HasEffect - ns=0;i=54 */
+
+static UA_StatusCode function_ua_namespace0_1_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");
+attr.description = UA_LOCALIZEDTEXT("", "The type for a reference to an event that may be raised when a transition occurs.");
+attr.writeMask = 0;
+attr.userWriteMask = 0;
+retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_REFERENCETYPE,
+UA_NODEID_NUMERIC(ns[0], 54),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_QUALIFIEDNAME(ns[0], "HasEffect"),
+UA_NODEID_NULL,
+(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_REFERENCETYPEATTRIBUTES],NULL, NULL);
+retVal |= UA_Server_addReference(server, UA_NODEID_NUMERIC(ns[0], 54), UA_NODEID_NUMERIC(ns[0], 45), UA_EXPANDEDNODEID_NUMERIC(ns[0], 32), false);
+return retVal;
+}
+
+static UA_StatusCode function_ua_namespace0_1_finish(UA_Server *server, UA_UInt16* ns) {
+
+return UA_Server_addNode_finish(server,
+UA_NODEID_NUMERIC(ns[0], 54)
+);
+}
+
+/* ToState - ns=0;i=52 */
+
+static UA_StatusCode function_ua_namespace0_2_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");
+attr.description = UA_LOCALIZEDTEXT("", "The type for a reference to the state after a transition.");
+attr.writeMask = 0;
+attr.userWriteMask = 0;
+retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_REFERENCETYPE,
+UA_NODEID_NUMERIC(ns[0], 52),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_QUALIFIEDNAME(ns[0], "ToState"),
+UA_NODEID_NULL,
+(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_REFERENCETYPEATTRIBUTES],NULL, NULL);
+retVal |= UA_Server_addReference(server, UA_NODEID_NUMERIC(ns[0], 52), UA_NODEID_NUMERIC(ns[0], 45), UA_EXPANDEDNODEID_NUMERIC(ns[0], 32), false);
+return retVal;
+}
+
+static UA_StatusCode function_ua_namespace0_2_finish(UA_Server *server, UA_UInt16* ns) {
+
+return UA_Server_addNode_finish(server,
+UA_NODEID_NUMERIC(ns[0], 52)
+);
+}
+
+/* HasCause - ns=0;i=53 */
+
+static UA_StatusCode function_ua_namespace0_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");
+attr.description = UA_LOCALIZEDTEXT("", "The type for a reference to a method that can cause a transition to occur.");
+attr.writeMask = 0;
+attr.userWriteMask = 0;
+retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_REFERENCETYPE,
+UA_NODEID_NUMERIC(ns[0], 53),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_QUALIFIEDNAME(ns[0], "HasCause"),
+UA_NODEID_NULL,
+(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_REFERENCETYPEATTRIBUTES],NULL, NULL);
+retVal |= UA_Server_addReference(server, UA_NODEID_NUMERIC(ns[0], 53), UA_NODEID_NUMERIC(ns[0], 45), UA_EXPANDEDNODEID_NUMERIC(ns[0], 32), false);
+return retVal;
+}
+
+static UA_StatusCode function_ua_namespace0_3_finish(UA_Server *server, UA_UInt16* ns) {
+
+return UA_Server_addNode_finish(server,
+UA_NODEID_NUMERIC(ns[0], 53)
+);
+}
+
+/* FromState - ns=0;i=51 */
+
+static UA_StatusCode function_ua_namespace0_4_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");
+attr.description = UA_LOCALIZEDTEXT("", "The type for a reference to the state before a transition.");
+attr.writeMask = 0;
+attr.userWriteMask = 0;
+retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_REFERENCETYPE,
+UA_NODEID_NUMERIC(ns[0], 51),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_QUALIFIEDNAME(ns[0], "FromState"),
+UA_NODEID_NULL,
+(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_REFERENCETYPEATTRIBUTES],NULL, NULL);
+retVal |= UA_Server_addReference(server, UA_NODEID_NUMERIC(ns[0], 51), UA_NODEID_NUMERIC(ns[0], 45), UA_EXPANDEDNODEID_NUMERIC(ns[0], 32), false);
+return retVal;
+}
+
+static UA_StatusCode function_ua_namespace0_4_finish(UA_Server *server, UA_UInt16* ns) {
+
+return UA_Server_addNode_finish(server,
+UA_NODEID_NUMERIC(ns[0], 51)
+);
+}
+
+/* EnumValueType - ns=0;i=7594 */
+
+static UA_StatusCode function_ua_namespace0_5_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.description = UA_LOCALIZEDTEXT("", "A mapping between a value of an enumerated type and a name and description.");
+attr.writeMask = 0;
+attr.userWriteMask = 0;
+retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_DATATYPE,
+UA_NODEID_NUMERIC(ns[0], 7594),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_QUALIFIEDNAME(ns[0], "EnumValueType"),
+UA_NODEID_NULL,
+(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_DATATYPEATTRIBUTES],NULL, NULL);
+retVal |= UA_Server_addReference(server, UA_NODEID_NUMERIC(ns[0], 7594), UA_NODEID_NUMERIC(ns[0], 45), UA_EXPANDEDNODEID_NUMERIC(ns[0], 22), false);
+return retVal;
+}
+
+static UA_StatusCode function_ua_namespace0_5_finish(UA_Server *server, UA_UInt16* ns) {
+
+return UA_Server_addNode_finish(server,
+UA_NODEID_NUMERIC(ns[0], 7594)
+);
+}
+
+/* ServerCapabilitiesType - ns=0;i=2013 */
+
+static UA_StatusCode function_ua_namespace0_6_begin(UA_Server *server, UA_UInt16* ns) {
+
+UA_StatusCode retVal = UA_STATUSCODE_GOOD;
+UA_ObjectTypeAttributes attr = UA_ObjectTypeAttributes_default;
+attr.displayName = UA_LOCALIZEDTEXT("", "ServerCapabilitiesType");
+attr.description = UA_LOCALIZEDTEXT("", "Describes the capabilities supported by the server.");
+attr.writeMask = 0;
+attr.userWriteMask = 0;
+retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_OBJECTTYPE,
+UA_NODEID_NUMERIC(ns[0], 2013),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_QUALIFIEDNAME(ns[0], "ServerCapabilitiesType"),
+UA_NODEID_NULL,
+(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_OBJECTTYPEATTRIBUTES],NULL, NULL);
+retVal |= UA_Server_addReference(server, UA_NODEID_NUMERIC(ns[0], 2013), UA_NODEID_NUMERIC(ns[0], 45), UA_EXPANDEDNODEID_NUMERIC(ns[0], 58), false);
+return retVal;
+}
+
+static UA_StatusCode function_ua_namespace0_6_finish(UA_Server *server, UA_UInt16* ns) {
+
+return UA_Server_addNode_finish(server,
+UA_NODEID_NUMERIC(ns[0], 2013)
+);
+}
+
+/* OperationLimitsType - ns=0;i=11564 */
+
+static UA_StatusCode function_ua_namespace0_7_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.description = UA_LOCALIZEDTEXT("", "Identifies the operation limits imposed by the server.");
+attr.writeMask = 0;
+attr.userWriteMask = 0;
+retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_OBJECTTYPE,
+UA_NODEID_NUMERIC(ns[0], 11564),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_QUALIFIEDNAME(ns[0], "OperationLimitsType"),
+UA_NODEID_NULL,
+(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_OBJECTTYPEATTRIBUTES],NULL, NULL);
+retVal |= UA_Server_addReference(server, UA_NODEID_NUMERIC(ns[0], 11564), UA_NODEID_NUMERIC(ns[0], 45), UA_EXPANDEDNODEID_NUMERIC(ns[0], 61), false);
+return retVal;
+}
+
+static UA_StatusCode function_ua_namespace0_7_finish(UA_Server *server, UA_UInt16* ns) {
+
+return UA_Server_addNode_finish(server,
+UA_NODEID_NUMERIC(ns[0], 11564)
+);
+}
+
+/* OperationLimits - ns=0;i=11551 */
+
+static UA_StatusCode function_ua_namespace0_8_begin(UA_Server *server, UA_UInt16* ns) {
+
+UA_StatusCode retVal = UA_STATUSCODE_GOOD;
+UA_ObjectAttributes attr = UA_ObjectAttributes_default;
+attr.displayName = UA_LOCALIZEDTEXT("", "OperationLimits");
+attr.description = UA_LOCALIZEDTEXT("", "Defines the limits supported by the server for different operations.");
+attr.writeMask = 0;
+attr.userWriteMask = 0;
+retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_OBJECT,
+UA_NODEID_NUMERIC(ns[0], 11551),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_QUALIFIEDNAME(ns[0], "OperationLimits"),
+UA_NODEID_NUMERIC(ns[0], 11564),
+(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_OBJECTATTRIBUTES],NULL, NULL);
+retVal |= UA_Server_addReference(server, UA_NODEID_NUMERIC(ns[0], 11551), UA_NODEID_NUMERIC(ns[0], 47), UA_EXPANDEDNODEID_NUMERIC(ns[0], 2013), false);
+return retVal;
+}
+
+static UA_StatusCode function_ua_namespace0_8_finish(UA_Server *server, UA_UInt16* ns) {
+
+return UA_Server_addNode_finish(server,
+UA_NODEID_NUMERIC(ns[0], 11551)
+);
+}
+
+/* BuildInfo - ns=0;i=338 */
+
+static UA_StatusCode function_ua_namespace0_9_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.description = UA_LOCALIZEDTEXT("", "");
+attr.writeMask = 0;
+attr.userWriteMask = 0;
+retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_DATATYPE,
+UA_NODEID_NUMERIC(ns[0], 338),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_QUALIFIEDNAME(ns[0], "BuildInfo"),
+UA_NODEID_NULL,
+(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_DATATYPEATTRIBUTES],NULL, NULL);
+retVal |= UA_Server_addReference(server, UA_NODEID_NUMERIC(ns[0], 338), UA_NODEID_NUMERIC(ns[0], 45), UA_EXPANDEDNODEID_NUMERIC(ns[0], 22), false);
+return retVal;
+}
+
+static UA_StatusCode function_ua_namespace0_9_finish(UA_Server *server, UA_UInt16* ns) {
+
+return UA_Server_addNode_finish(server,
+UA_NODEID_NUMERIC(ns[0], 338)
+);
+}
+
+/* ServerType - ns=0;i=2004 */
+
+static UA_StatusCode function_ua_namespace0_10_begin(UA_Server *server, UA_UInt16* ns) {
+
+UA_StatusCode retVal = UA_STATUSCODE_GOOD;
+UA_ObjectTypeAttributes attr = UA_ObjectTypeAttributes_default;
+attr.displayName = UA_LOCALIZEDTEXT("", "ServerType");
+attr.description = UA_LOCALIZEDTEXT("", "Specifies the current status and capabilities of the server.");
+attr.writeMask = 0;
+attr.userWriteMask = 0;
+retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_OBJECTTYPE,
+UA_NODEID_NUMERIC(ns[0], 2004),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_QUALIFIEDNAME(ns[0], "ServerType"),
+UA_NODEID_NULL,
+(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_OBJECTTYPEATTRIBUTES],NULL, NULL);
+retVal |= UA_Server_addReference(server, UA_NODEID_NUMERIC(ns[0], 2004), UA_NODEID_NUMERIC(ns[0], 45), UA_EXPANDEDNODEID_NUMERIC(ns[0], 58), false);
+return retVal;
+}
+
+static UA_StatusCode function_ua_namespace0_10_finish(UA_Server *server, UA_UInt16* ns) {
+
+return UA_Server_addNode_finish(server,
+UA_NODEID_NUMERIC(ns[0], 2004)
+);
+}
+
+/* Server - ns=0;i=2253 */
+
+static UA_StatusCode function_ua_namespace0_11_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");
+attr.description = UA_LOCALIZEDTEXT("", "");
+attr.writeMask = 0;
+attr.userWriteMask = 0;
+retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_OBJECT,
+UA_NODEID_NUMERIC(ns[0], 2253),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_QUALIFIEDNAME(ns[0], "Server"),
+UA_NODEID_NUMERIC(ns[0], 2004),
+(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_OBJECTATTRIBUTES],NULL, NULL);
+retVal |= UA_Server_addReference(server, UA_NODEID_NUMERIC(ns[0], 2253), UA_NODEID_NUMERIC(ns[0], 35), UA_EXPANDEDNODEID_NUMERIC(ns[0], 85), false);
+return retVal;
+}
+
+static UA_StatusCode function_ua_namespace0_11_finish(UA_Server *server, UA_UInt16* ns) {
+
+return UA_Server_addNode_finish(server,
+UA_NODEID_NUMERIC(ns[0], 2253)
+);
+}
+
+/* GetMonitoredItems - ns=0;i=11492 */
+
+static UA_StatusCode function_ua_namespace0_12_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");
+attr.description = UA_LOCALIZEDTEXT("", "");
+attr.writeMask = 0;
+attr.userWriteMask = 0;
+retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_METHOD,
+UA_NODEID_NUMERIC(ns[0], 11492),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_QUALIFIEDNAME(ns[0], "GetMonitoredItems"),
+UA_NODEID_NULL,
+(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_METHODATTRIBUTES],NULL, NULL);
+retVal |= UA_Server_addReference(server, UA_NODEID_NUMERIC(ns[0], 11492), UA_NODEID_NUMERIC(ns[0], 47), UA_EXPANDEDNODEID_NUMERIC(ns[0], 2253), false);
+return retVal;
+#else
+return UA_STATUSCODE_GOOD;
+#endif /* UA_ENABLE_METHODCALLS */
+}
+
+static UA_StatusCode function_ua_namespace0_12_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 */
+}
+
+/* ServerCapabilities - ns=0;i=2268 */
+
+static UA_StatusCode function_ua_namespace0_13_begin(UA_Server *server, UA_UInt16* ns) {
+
+UA_StatusCode retVal = UA_STATUSCODE_GOOD;
+UA_ObjectAttributes attr = UA_ObjectAttributes_default;
+attr.displayName = UA_LOCALIZEDTEXT("", "ServerCapabilities");
+attr.description = UA_LOCALIZEDTEXT("", "Describes capabilities supported by the server.");
+attr.writeMask = 0;
+attr.userWriteMask = 0;
+retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_OBJECT,
+UA_NODEID_NUMERIC(ns[0], 2268),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_QUALIFIEDNAME(ns[0], "ServerCapabilities"),
+UA_NODEID_NUMERIC(ns[0], 2013),
+(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_OBJECTATTRIBUTES],NULL, NULL);
+retVal |= UA_Server_addReference(server, UA_NODEID_NUMERIC(ns[0], 2268), UA_NODEID_NUMERIC(ns[0], 47), UA_EXPANDEDNODEID_NUMERIC(ns[0], 2253), false);
+return retVal;
+}
+
+static UA_StatusCode function_ua_namespace0_13_finish(UA_Server *server, UA_UInt16* ns) {
+
+return UA_Server_addNode_finish(server,
+UA_NODEID_NUMERIC(ns[0], 2268)
+);
+}
+
+/* AggregateFunctions - ns=0;i=2997 */
+
+static UA_StatusCode function_ua_namespace0_14_begin(UA_Server *server, UA_UInt16* ns) {
+
+UA_StatusCode retVal = UA_STATUSCODE_GOOD;
+UA_ObjectAttributes attr = UA_ObjectAttributes_default;
+attr.displayName = UA_LOCALIZEDTEXT("", "AggregateFunctions");
+attr.description = UA_LOCALIZEDTEXT("", "A folder for the real time aggregates supported by the server.");
+attr.writeMask = 0;
+attr.userWriteMask = 0;
+retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_OBJECT,
+UA_NODEID_NUMERIC(ns[0], 2997),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_QUALIFIEDNAME(ns[0], "AggregateFunctions"),
+UA_NODEID_NUMERIC(ns[0], 61),
+(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_OBJECTATTRIBUTES],NULL, NULL);
+retVal |= UA_Server_addReference(server, UA_NODEID_NUMERIC(ns[0], 2997), UA_NODEID_NUMERIC(ns[0], 47), UA_EXPANDEDNODEID_NUMERIC(ns[0], 2268), false);
+return retVal;
+}
+
+static UA_StatusCode function_ua_namespace0_14_finish(UA_Server *server, UA_UInt16* ns) {
+
+return UA_Server_addNode_finish(server,
+UA_NODEID_NUMERIC(ns[0], 2997)
+);
+}
+
+/* ModellingRules - ns=0;i=2996 */
+
+static UA_StatusCode function_ua_namespace0_15_begin(UA_Server *server, UA_UInt16* ns) {
+
+UA_StatusCode retVal = UA_STATUSCODE_GOOD;
+UA_ObjectAttributes attr = UA_ObjectAttributes_default;
+attr.displayName = UA_LOCALIZEDTEXT("", "ModellingRules");
+attr.description = UA_LOCALIZEDTEXT("", "A folder for the modelling rules supported by the server.");
+attr.writeMask = 0;
+attr.userWriteMask = 0;
+retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_OBJECT,
+UA_NODEID_NUMERIC(ns[0], 2996),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_QUALIFIEDNAME(ns[0], "ModellingRules"),
+UA_NODEID_NUMERIC(ns[0], 61),
+(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_OBJECTATTRIBUTES],NULL, NULL);
+retVal |= UA_Server_addReference(server, UA_NODEID_NUMERIC(ns[0], 2996), UA_NODEID_NUMERIC(ns[0], 47), UA_EXPANDEDNODEID_NUMERIC(ns[0], 2268), false);
+return retVal;
+}
+
+static UA_StatusCode function_ua_namespace0_15_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_ua_namespace0_16_begin(UA_Server *server, UA_UInt16* ns) {
+
+UA_StatusCode retVal = UA_STATUSCODE_GOOD;
+UA_ObjectAttributes attr = UA_ObjectAttributes_default;
+attr.displayName = UA_LOCALIZEDTEXT("", "OperationLimits");
+attr.description = UA_LOCALIZEDTEXT("", "Defines the limits supported by the server for different operations.");
+attr.writeMask = 0;
+attr.userWriteMask = 0;
+retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_OBJECT,
+UA_NODEID_NUMERIC(ns[0], 11704),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_QUALIFIEDNAME(ns[0], "OperationLimits"),
+UA_NODEID_NUMERIC(ns[0], 11564),
+(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_OBJECTATTRIBUTES],NULL, NULL);
+retVal |= UA_Server_addReference(server, UA_NODEID_NUMERIC(ns[0], 11704), UA_NODEID_NUMERIC(ns[0], 47), UA_EXPANDEDNODEID_NUMERIC(ns[0], 2268), false);
+return retVal;
+}
+
+static UA_StatusCode function_ua_namespace0_16_finish(UA_Server *server, UA_UInt16* ns) {
+
+return UA_Server_addNode_finish(server,
+UA_NODEID_NUMERIC(ns[0], 11704)
+);
+}
+
+/* ServerDiagnosticsSummaryType - ns=0;i=2150 */
+
+static UA_StatusCode function_ua_namespace0_17_begin(UA_Server *server, UA_UInt16* ns) {
+
+UA_StatusCode retVal = UA_STATUSCODE_GOOD;
+UA_VariableTypeAttributes attr = UA_VariableTypeAttributes_default;
+attr.valueRank = (UA_Int32)-2;
+attr.dataType = UA_NODEID_NUMERIC(ns[0], 24);
+attr.displayName = UA_LOCALIZEDTEXT("", "ServerDiagnosticsSummaryType");
+attr.description = UA_LOCALIZEDTEXT("", "");
+attr.writeMask = 0;
+attr.userWriteMask = 0;
+retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_VARIABLETYPE,
+UA_NODEID_NUMERIC(ns[0], 2150),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_QUALIFIEDNAME(ns[0], "ServerDiagnosticsSummaryType"),
+UA_NODEID_NUMERIC(ns[0], 63),
+(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_VARIABLETYPEATTRIBUTES],NULL, NULL);
+retVal |= UA_Server_addReference(server, UA_NODEID_NUMERIC(ns[0], 2150), UA_NODEID_NUMERIC(ns[0], 45), UA_EXPANDEDNODEID_NUMERIC(ns[0], 63), false);
+return retVal;
+}
+
+static UA_StatusCode function_ua_namespace0_17_finish(UA_Server *server, UA_UInt16* ns) {
+
+return UA_Server_addNode_finish(server,
+UA_NODEID_NUMERIC(ns[0], 2150)
+);
+}
+
+/* PublishingIntervalCount - ns=0;i=2159 */
+
+static UA_StatusCode function_ua_namespace0_18_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.dataType = UA_NODEID_NUMERIC(ns[0], 7);
+UA_Variant_setScalar(&attr.value, NULL, &UA_TYPES[UA_TYPES_UINT32]);
+attr.displayName = UA_LOCALIZEDTEXT("", "PublishingIntervalCount");
+attr.description = UA_LOCALIZEDTEXT("", "");
+attr.writeMask = 0;
+attr.userWriteMask = 0;
+retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_VARIABLE,
+UA_NODEID_NUMERIC(ns[0], 2159),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_QUALIFIEDNAME(ns[0], "PublishingIntervalCount"),
+UA_NODEID_NUMERIC(ns[0], 63),
+(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
+retVal |= UA_Server_addReference(server, UA_NODEID_NUMERIC(ns[0], 2159), UA_NODEID_NUMERIC(ns[0], 47), UA_EXPANDEDNODEID_NUMERIC(ns[0], 2150), false);
+return retVal;
+}
+
+static UA_StatusCode function_ua_namespace0_18_finish(UA_Server *server, UA_UInt16* ns) {
+
+return UA_Server_addNode_finish(server,
+UA_NODEID_NUMERIC(ns[0], 2159)
+);
+}
+
+/* SecurityRejectedSessionCount - ns=0;i=2154 */
+
+static UA_StatusCode function_ua_namespace0_19_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.dataType = UA_NODEID_NUMERIC(ns[0], 7);
+UA_Variant_setScalar(&attr.value, NULL, &UA_TYPES[UA_TYPES_UINT32]);
+attr.displayName = UA_LOCALIZEDTEXT("", "SecurityRejectedSessionCount");
+attr.description = UA_LOCALIZEDTEXT("", "");
+attr.writeMask = 0;
+attr.userWriteMask = 0;
+retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_VARIABLE,
+UA_NODEID_NUMERIC(ns[0], 2154),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_QUALIFIEDNAME(ns[0], "SecurityRejectedSessionCount"),
+UA_NODEID_NUMERIC(ns[0], 63),
+(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
+retVal |= UA_Server_addReference(server, UA_NODEID_NUMERIC(ns[0], 2154), UA_NODEID_NUMERIC(ns[0], 47), UA_EXPANDEDNODEID_NUMERIC(ns[0], 2150), false);
+return retVal;
+}
+
+static UA_StatusCode function_ua_namespace0_19_finish(UA_Server *server, UA_UInt16* ns) {
+
+return UA_Server_addNode_finish(server,
+UA_NODEID_NUMERIC(ns[0], 2154)
+);
+}
+
+/* SecurityRejectedRequestsCount - ns=0;i=2162 */
+
+static UA_StatusCode function_ua_namespace0_20_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.dataType = UA_NODEID_NUMERIC(ns[0], 7);
+UA_Variant_setScalar(&attr.value, NULL, &UA_TYPES[UA_TYPES_UINT32]);
+attr.displayName = UA_LOCALIZEDTEXT("", "SecurityRejectedRequestsCount");
+attr.description = UA_LOCALIZEDTEXT("", "");
+attr.writeMask = 0;
+attr.userWriteMask = 0;
+retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_VARIABLE,
+UA_NODEID_NUMERIC(ns[0], 2162),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_QUALIFIEDNAME(ns[0], "SecurityRejectedRequestsCount"),
+UA_NODEID_NUMERIC(ns[0], 63),
+(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
+retVal |= UA_Server_addReference(server, UA_NODEID_NUMERIC(ns[0], 2162), UA_NODEID_NUMERIC(ns[0], 47), UA_EXPANDEDNODEID_NUMERIC(ns[0], 2150), false);
+return retVal;
+}
+
+static UA_StatusCode function_ua_namespace0_20_finish(UA_Server *server, UA_UInt16* ns) {
+
+return UA_Server_addNode_finish(server,
+UA_NODEID_NUMERIC(ns[0], 2162)
+);
+}
+
+/* RejectedRequestsCount - ns=0;i=2163 */
+
+static UA_StatusCode function_ua_namespace0_21_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.dataType = UA_NODEID_NUMERIC(ns[0], 7);
+UA_Variant_setScalar(&attr.value, NULL, &UA_TYPES[UA_TYPES_UINT32]);
+attr.displayName = UA_LOCALIZEDTEXT("", "RejectedRequestsCount");
+attr.description = UA_LOCALIZEDTEXT("", "");
+attr.writeMask = 0;
+attr.userWriteMask = 0;
+retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_VARIABLE,
+UA_NODEID_NUMERIC(ns[0], 2163),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_QUALIFIEDNAME(ns[0], "RejectedRequestsCount"),
+UA_NODEID_NUMERIC(ns[0], 63),
+(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
+retVal |= UA_Server_addReference(server, UA_NODEID_NUMERIC(ns[0], 2163), UA_NODEID_NUMERIC(ns[0], 47), UA_EXPANDEDNODEID_NUMERIC(ns[0], 2150), false);
+return retVal;
+}
+
+static UA_StatusCode function_ua_namespace0_21_finish(UA_Server *server, UA_UInt16* ns) {
+
+return UA_Server_addNode_finish(server,
+UA_NODEID_NUMERIC(ns[0], 2163)
+);
+}
+
+/* RejectedSessionCount - ns=0;i=2155 */
+
+static UA_StatusCode function_ua_namespace0_22_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.dataType = UA_NODEID_NUMERIC(ns[0], 7);
+UA_Variant_setScalar(&attr.value, NULL, &UA_TYPES[UA_TYPES_UINT32]);
+attr.displayName = UA_LOCALIZEDTEXT("", "RejectedSessionCount");
+attr.description = UA_LOCALIZEDTEXT("", "");
+attr.writeMask = 0;
+attr.userWriteMask = 0;
+retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_VARIABLE,
+UA_NODEID_NUMERIC(ns[0], 2155),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_QUALIFIEDNAME(ns[0], "RejectedSessionCount"),
+UA_NODEID_NUMERIC(ns[0], 63),
+(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
+retVal |= UA_Server_addReference(server, UA_NODEID_NUMERIC(ns[0], 2155), UA_NODEID_NUMERIC(ns[0], 47), UA_EXPANDEDNODEID_NUMERIC(ns[0], 2150), false);
+return retVal;
+}
+
+static UA_StatusCode function_ua_namespace0_22_finish(UA_Server *server, UA_UInt16* ns) {
+
+return UA_Server_addNode_finish(server,
+UA_NODEID_NUMERIC(ns[0], 2155)
+);
+}
+
+/* CumulatedSubscriptionCount - ns=0;i=2161 */
+
+static UA_StatusCode function_ua_namespace0_23_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.dataType = UA_NODEID_NUMERIC(ns[0], 7);
+UA_Variant_setScalar(&attr.value, NULL, &UA_TYPES[UA_TYPES_UINT32]);
+attr.displayName = UA_LOCALIZEDTEXT("", "CumulatedSubscriptionCount");
+attr.description = UA_LOCALIZEDTEXT("", "");
+attr.writeMask = 0;
+attr.userWriteMask = 0;
+retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_VARIABLE,
+UA_NODEID_NUMERIC(ns[0], 2161),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_QUALIFIEDNAME(ns[0], "CumulatedSubscriptionCount"),
+UA_NODEID_NUMERIC(ns[0], 63),
+(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
+retVal |= UA_Server_addReference(server, UA_NODEID_NUMERIC(ns[0], 2161), UA_NODEID_NUMERIC(ns[0], 47), UA_EXPANDEDNODEID_NUMERIC(ns[0], 2150), false);
+return retVal;
+}
+
+static UA_StatusCode function_ua_namespace0_23_finish(UA_Server *server, UA_UInt16* ns) {
+
+return UA_Server_addNode_finish(server,
+UA_NODEID_NUMERIC(ns[0], 2161)
+);
+}
+
+/* CumulatedSessionCount - ns=0;i=2153 */
+
+static UA_StatusCode function_ua_namespace0_24_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.dataType = UA_NODEID_NUMERIC(ns[0], 7);
+UA_Variant_setScalar(&attr.value, NULL, &UA_TYPES[UA_TYPES_UINT32]);
+attr.displayName = UA_LOCALIZEDTEXT("", "CumulatedSessionCount");
+attr.description = UA_LOCALIZEDTEXT("", "");
+attr.writeMask = 0;
+attr.userWriteMask = 0;
+retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_VARIABLE,
+UA_NODEID_NUMERIC(ns[0], 2153),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_QUALIFIEDNAME(ns[0], "CumulatedSessionCount"),
+UA_NODEID_NUMERIC(ns[0], 63),
+(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
+retVal |= UA_Server_addReference(server, UA_NODEID_NUMERIC(ns[0], 2153), UA_NODEID_NUMERIC(ns[0], 47), UA_EXPANDEDNODEID_NUMERIC(ns[0], 2150), false);
+return retVal;
+}
+
+static UA_StatusCode function_ua_namespace0_24_finish(UA_Server *server, UA_UInt16* ns) {
+
+return UA_Server_addNode_finish(server,
+UA_NODEID_NUMERIC(ns[0], 2153)
+);
+}
+
+/* CurrentSessionCount - ns=0;i=2152 */
+
+static UA_StatusCode function_ua_namespace0_25_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.dataType = UA_NODEID_NUMERIC(ns[0], 7);
+UA_Variant_setScalar(&attr.value, NULL, &UA_TYPES[UA_TYPES_UINT32]);
+attr.displayName = UA_LOCALIZEDTEXT("", "CurrentSessionCount");
+attr.description = UA_LOCALIZEDTEXT("", "");
+attr.writeMask = 0;
+attr.userWriteMask = 0;
+retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_VARIABLE,
+UA_NODEID_NUMERIC(ns[0], 2152),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_QUALIFIEDNAME(ns[0], "CurrentSessionCount"),
+UA_NODEID_NUMERIC(ns[0], 63),
+(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
+retVal |= UA_Server_addReference(server, UA_NODEID_NUMERIC(ns[0], 2152), UA_NODEID_NUMERIC(ns[0], 47), UA_EXPANDEDNODEID_NUMERIC(ns[0], 2150), false);
+return retVal;
+}
+
+static UA_StatusCode function_ua_namespace0_25_finish(UA_Server *server, UA_UInt16* ns) {
+
+return UA_Server_addNode_finish(server,
+UA_NODEID_NUMERIC(ns[0], 2152)
+);
+}
+
+/* ServerViewCount - ns=0;i=2151 */
+
+static UA_StatusCode function_ua_namespace0_26_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.dataType = UA_NODEID_NUMERIC(ns[0], 7);
+UA_Variant_setScalar(&attr.value, NULL, &UA_TYPES[UA_TYPES_UINT32]);
+attr.displayName = UA_LOCALIZEDTEXT("", "ServerViewCount");
+attr.description = UA_LOCALIZEDTEXT("", "");
+attr.writeMask = 0;
+attr.userWriteMask = 0;
+retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_VARIABLE,
+UA_NODEID_NUMERIC(ns[0], 2151),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_QUALIFIEDNAME(ns[0], "ServerViewCount"),
+UA_NODEID_NUMERIC(ns[0], 63),
+(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
+retVal |= UA_Server_addReference(server, UA_NODEID_NUMERIC(ns[0], 2151), UA_NODEID_NUMERIC(ns[0], 47), UA_EXPANDEDNODEID_NUMERIC(ns[0], 2150), false);
+return retVal;
+}
+
+static UA_StatusCode function_ua_namespace0_26_finish(UA_Server *server, UA_UInt16* ns) {
+
+return UA_Server_addNode_finish(server,
+UA_NODEID_NUMERIC(ns[0], 2151)
+);
+}
+
+/* SessionAbortCount - ns=0;i=2157 */
+
+static UA_StatusCode function_ua_namespace0_27_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.dataType = UA_NODEID_NUMERIC(ns[0], 7);
+UA_Variant_setScalar(&attr.value, NULL, &UA_TYPES[UA_TYPES_UINT32]);
+attr.displayName = UA_LOCALIZEDTEXT("", "SessionAbortCount");
+attr.description = UA_LOCALIZEDTEXT("", "");
+attr.writeMask = 0;
+attr.userWriteMask = 0;
+retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_VARIABLE,
+UA_NODEID_NUMERIC(ns[0], 2157),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_QUALIFIEDNAME(ns[0], "SessionAbortCount"),
+UA_NODEID_NUMERIC(ns[0], 63),
+(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
+retVal |= UA_Server_addReference(server, UA_NODEID_NUMERIC(ns[0], 2157), UA_NODEID_NUMERIC(ns[0], 47), UA_EXPANDEDNODEID_NUMERIC(ns[0], 2150), false);
+return retVal;
+}
+
+static UA_StatusCode function_ua_namespace0_27_finish(UA_Server *server, UA_UInt16* ns) {
+
+return UA_Server_addNode_finish(server,
+UA_NODEID_NUMERIC(ns[0], 2157)
+);
+}
+
+/* SessionTimeoutCount - ns=0;i=2156 */
+
+static UA_StatusCode function_ua_namespace0_28_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.dataType = UA_NODEID_NUMERIC(ns[0], 7);
+UA_Variant_setScalar(&attr.value, NULL, &UA_TYPES[UA_TYPES_UINT32]);
+attr.displayName = UA_LOCALIZEDTEXT("", "SessionTimeoutCount");
+attr.description = UA_LOCALIZEDTEXT("", "");
+attr.writeMask = 0;
+attr.userWriteMask = 0;
+retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_VARIABLE,
+UA_NODEID_NUMERIC(ns[0], 2156),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_QUALIFIEDNAME(ns[0], "SessionTimeoutCount"),
+UA_NODEID_NUMERIC(ns[0], 63),
+(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
+retVal |= UA_Server_addReference(server, UA_NODEID_NUMERIC(ns[0], 2156), UA_NODEID_NUMERIC(ns[0], 47), UA_EXPANDEDNODEID_NUMERIC(ns[0], 2150), false);
+return retVal;
+}
+
+static UA_StatusCode function_ua_namespace0_28_finish(UA_Server *server, UA_UInt16* ns) {
+
+return UA_Server_addNode_finish(server,
+UA_NODEID_NUMERIC(ns[0], 2156)
+);
+}
+
+/* CurrentSubscriptionCount - ns=0;i=2160 */
+
+static UA_StatusCode function_ua_namespace0_29_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.dataType = UA_NODEID_NUMERIC(ns[0], 7);
+UA_Variant_setScalar(&attr.value, NULL, &UA_TYPES[UA_TYPES_UINT32]);
+attr.displayName = UA_LOCALIZEDTEXT("", "CurrentSubscriptionCount");
+attr.description = UA_LOCALIZEDTEXT("", "");
+attr.writeMask = 0;
+attr.userWriteMask = 0;
+retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_VARIABLE,
+UA_NODEID_NUMERIC(ns[0], 2160),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_QUALIFIEDNAME(ns[0], "CurrentSubscriptionCount"),
+UA_NODEID_NUMERIC(ns[0], 63),
+(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
+retVal |= UA_Server_addReference(server, UA_NODEID_NUMERIC(ns[0], 2160), UA_NODEID_NUMERIC(ns[0], 47), UA_EXPANDEDNODEID_NUMERIC(ns[0], 2150), false);
+return retVal;
+}
+
+static UA_StatusCode function_ua_namespace0_29_finish(UA_Server *server, UA_UInt16* ns) {
+
+return UA_Server_addNode_finish(server,
+UA_NODEID_NUMERIC(ns[0], 2160)
+);
+}
+
+/* BuildInfoType - ns=0;i=3051 */
+
+static UA_StatusCode function_ua_namespace0_30_begin(UA_Server *server, UA_UInt16* ns) {
+
+UA_StatusCode retVal = UA_STATUSCODE_GOOD;
+UA_VariableTypeAttributes attr = UA_VariableTypeAttributes_default;
+attr.valueRank = (UA_Int32)-2;
+attr.dataType = UA_NODEID_NUMERIC(ns[0], 24);
+attr.displayName = UA_LOCALIZEDTEXT("", "BuildInfoType");
+attr.description = UA_LOCALIZEDTEXT("", "");
+attr.writeMask = 0;
+attr.userWriteMask = 0;
+retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_VARIABLETYPE,
+UA_NODEID_NUMERIC(ns[0], 3051),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_QUALIFIEDNAME(ns[0], "BuildInfoType"),
+UA_NODEID_NUMERIC(ns[0], 63),
+(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_VARIABLETYPEATTRIBUTES],NULL, NULL);
+retVal |= UA_Server_addReference(server, UA_NODEID_NUMERIC(ns[0], 3051), UA_NODEID_NUMERIC(ns[0], 45), UA_EXPANDEDNODEID_NUMERIC(ns[0], 63), false);
+return retVal;
+}
+
+static UA_StatusCode function_ua_namespace0_30_finish(UA_Server *server, UA_UInt16* ns) {
+
+return UA_Server_addNode_finish(server,
+UA_NODEID_NUMERIC(ns[0], 3051)
+);
+}
+
+/* Image - ns=0;i=30 */
+
+static UA_StatusCode function_ua_namespace0_31_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");
+attr.description = UA_LOCALIZEDTEXT("", "Describes a value that is an image encoded as a string of bytes.");
+attr.writeMask = 0;
+attr.userWriteMask = 0;
+retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_DATATYPE,
+UA_NODEID_NUMERIC(ns[0], 30),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_QUALIFIEDNAME(ns[0], "Image"),
+UA_NODEID_NULL,
+(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_DATATYPEATTRIBUTES],NULL, NULL);
+retVal |= UA_Server_addReference(server, UA_NODEID_NUMERIC(ns[0], 30), UA_NODEID_NUMERIC(ns[0], 45), UA_EXPANDEDNODEID_NUMERIC(ns[0], 15), false);
+return retVal;
+}
+
+static UA_StatusCode function_ua_namespace0_31_finish(UA_Server *server, UA_UInt16* ns) {
+
+return UA_Server_addNode_finish(server,
+UA_NODEID_NUMERIC(ns[0], 30)
+);
+}
+
+/* Decimal - ns=0;i=50 */
+
+static UA_StatusCode function_ua_namespace0_32_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.description = UA_LOCALIZEDTEXT("", "Describes an arbitrary precision decimal value.");
+attr.writeMask = 0;
+attr.userWriteMask = 0;
+retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_DATATYPE,
+UA_NODEID_NUMERIC(ns[0], 50),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_QUALIFIEDNAME(ns[0], "Decimal"),
+UA_NODEID_NULL,
+(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_DATATYPEATTRIBUTES],NULL, NULL);
+retVal |= UA_Server_addReference(server, UA_NODEID_NUMERIC(ns[0], 50), UA_NODEID_NUMERIC(ns[0], 45), UA_EXPANDEDNODEID_NUMERIC(ns[0], 26), false);
+return retVal;
+}
+
+static UA_StatusCode function_ua_namespace0_32_finish(UA_Server *server, UA_UInt16* ns) {
+
+return UA_Server_addNode_finish(server,
+UA_NODEID_NUMERIC(ns[0], 50)
+);
+}
+
+/* Enumeration - ns=0;i=29 */
+
+static UA_StatusCode function_ua_namespace0_33_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");
+attr.description = UA_LOCALIZEDTEXT("", "Describes a value that is an enumerated DataType.");
+attr.writeMask = 0;
+attr.userWriteMask = 0;
+retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_DATATYPE,
+UA_NODEID_NUMERIC(ns[0], 29),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_QUALIFIEDNAME(ns[0], "Enumeration"),
+UA_NODEID_NULL,
+(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_DATATYPEATTRIBUTES],NULL, NULL);
+retVal |= UA_Server_addReference(server, UA_NODEID_NUMERIC(ns[0], 29), UA_NODEID_NUMERIC(ns[0], 45), UA_EXPANDEDNODEID_NUMERIC(ns[0], 24), false);
+return retVal;
+}
+
+static UA_StatusCode function_ua_namespace0_33_finish(UA_Server *server, UA_UInt16* ns) {
+
+return UA_Server_addNode_finish(server,
+UA_NODEID_NUMERIC(ns[0], 29)
+);
+}
+
+/* NamingRuleType - ns=0;i=120 */
+
+static UA_StatusCode function_ua_namespace0_34_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.description = UA_LOCALIZEDTEXT("", "Describes a value that specifies the significance of the BrowseName for an instance declaration.");
+attr.writeMask = 0;
+attr.userWriteMask = 0;
+retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_DATATYPE,
+UA_NODEID_NUMERIC(ns[0], 120),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_QUALIFIEDNAME(ns[0], "NamingRuleType"),
+UA_NODEID_NULL,
+(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_DATATYPEATTRIBUTES],NULL, NULL);
+retVal |= UA_Server_addReference(server, UA_NODEID_NUMERIC(ns[0], 120), UA_NODEID_NUMERIC(ns[0], 45), UA_EXPANDEDNODEID_NUMERIC(ns[0], 29), false);
+return retVal;
+}
+
+static UA_StatusCode function_ua_namespace0_34_finish(UA_Server *server, UA_UInt16* ns) {
+
+return UA_Server_addNode_finish(server,
+UA_NODEID_NUMERIC(ns[0], 120)
+);
+}
+
+/* RedundancySupport - ns=0;i=851 */
+
+static UA_StatusCode function_ua_namespace0_35_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.description = UA_LOCALIZEDTEXT("", "");
+attr.writeMask = 0;
+attr.userWriteMask = 0;
+retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_DATATYPE,
+UA_NODEID_NUMERIC(ns[0], 851),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_QUALIFIEDNAME(ns[0], "RedundancySupport"),
+UA_NODEID_NULL,
+(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_DATATYPEATTRIBUTES],NULL, NULL);
+retVal |= UA_Server_addReference(server, UA_NODEID_NUMERIC(ns[0], 851), UA_NODEID_NUMERIC(ns[0], 45), UA_EXPANDEDNODEID_NUMERIC(ns[0], 29), false);
+return retVal;
+}
+
+static UA_StatusCode function_ua_namespace0_35_finish(UA_Server *server, UA_UInt16* ns) {
+
+return UA_Server_addNode_finish(server,
+UA_NODEID_NUMERIC(ns[0], 851)
+);
+}
+
+/* ServerState - ns=0;i=852 */
+
+static UA_StatusCode function_ua_namespace0_36_begin(UA_Server *server, UA_UInt16* ns) {
+
+UA_StatusCode retVal = UA_STATUSCODE_GOOD;
+UA_DataTypeAttributes attr = UA_DataTypeAttributes_default;
+attr.displayName = UA_LOCALIZEDTEXT("", "ServerState");
+attr.description = UA_LOCALIZEDTEXT("", "");
+attr.writeMask = 0;
+attr.userWriteMask = 0;
+retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_DATATYPE,
+UA_NODEID_NUMERIC(ns[0], 852),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_QUALIFIEDNAME(ns[0], "ServerState"),
+UA_NODEID_NULL,
+(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_DATATYPEATTRIBUTES],NULL, NULL);
+retVal |= UA_Server_addReference(server, UA_NODEID_NUMERIC(ns[0], 852), UA_NODEID_NUMERIC(ns[0], 45), UA_EXPANDEDNODEID_NUMERIC(ns[0], 29), false);
+return retVal;
+}
+
+static UA_StatusCode function_ua_namespace0_36_finish(UA_Server *server, UA_UInt16* ns) {
+
+return UA_Server_addNode_finish(server,
+UA_NODEID_NUMERIC(ns[0], 852)
+);
+}
+
+/* DiagnosticInfo - ns=0;i=25 */
+
+static UA_StatusCode function_ua_namespace0_37_begin(UA_Server *server, UA_UInt16* ns) {
+
+UA_StatusCode retVal = UA_STATUSCODE_GOOD;
+UA_DataTypeAttributes attr = UA_DataTypeAttributes_default;
+attr.displayName = UA_LOCALIZEDTEXT("", "DiagnosticInfo");
+attr.description = UA_LOCALIZEDTEXT("", "Describes a value that is a structure containing diagnostics associated with a StatusCode.");
+attr.writeMask = 0;
+attr.userWriteMask = 0;
+retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_DATATYPE,
+UA_NODEID_NUMERIC(ns[0], 25),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_QUALIFIEDNAME(ns[0], "DiagnosticInfo"),
+UA_NODEID_NULL,
+(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_DATATYPEATTRIBUTES],NULL, NULL);
+retVal |= UA_Server_addReference(server, UA_NODEID_NUMERIC(ns[0], 25), UA_NODEID_NUMERIC(ns[0], 45), UA_EXPANDEDNODEID_NUMERIC(ns[0], 24), false);
+return retVal;
+}
+
+static UA_StatusCode function_ua_namespace0_37_finish(UA_Server *server, UA_UInt16* ns) {
+
+return UA_Server_addNode_finish(server,
+UA_NODEID_NUMERIC(ns[0], 25)
+);
+}
+
+/* DataValue - ns=0;i=23 */
+
+static UA_StatusCode function_ua_namespace0_38_begin(UA_Server *server, UA_UInt16* ns) {
+
+UA_StatusCode retVal = UA_STATUSCODE_GOOD;
+UA_DataTypeAttributes attr = UA_DataTypeAttributes_default;
+attr.displayName = UA_LOCALIZEDTEXT("", "DataValue");
+attr.description = UA_LOCALIZEDTEXT("", "Describes a value that is a structure containing a value, a status code and timestamps.");
+attr.writeMask = 0;
+attr.userWriteMask = 0;
+retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_DATATYPE,
+UA_NODEID_NUMERIC(ns[0], 23),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_QUALIFIEDNAME(ns[0], "DataValue"),
+UA_NODEID_NULL,
+(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_DATATYPEATTRIBUTES],NULL, NULL);
+retVal |= UA_Server_addReference(server, UA_NODEID_NUMERIC(ns[0], 23), UA_NODEID_NUMERIC(ns[0], 45), UA_EXPANDEDNODEID_NUMERIC(ns[0], 24), false);
+return retVal;
+}
+
+static UA_StatusCode function_ua_namespace0_38_finish(UA_Server *server, UA_UInt16* ns) {
+
+return UA_Server_addNode_finish(server,
+UA_NODEID_NUMERIC(ns[0], 23)
+);
+}
+
+/* ServerRedundancyType - ns=0;i=2034 */
+
+static UA_StatusCode function_ua_namespace0_39_begin(UA_Server *server, UA_UInt16* ns) {
+
+UA_StatusCode retVal = UA_STATUSCODE_GOOD;
+UA_ObjectTypeAttributes attr = UA_ObjectTypeAttributes_default;
+attr.displayName = UA_LOCALIZEDTEXT("", "ServerRedundancyType");
+attr.description = UA_LOCALIZEDTEXT("", "A base type for an object that describe how a server supports redundancy.");
+attr.writeMask = 0;
+attr.userWriteMask = 0;
+retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_OBJECTTYPE,
+UA_NODEID_NUMERIC(ns[0], 2034),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_QUALIFIEDNAME(ns[0], "ServerRedundancyType"),
+UA_NODEID_NULL,
+(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_OBJECTTYPEATTRIBUTES],NULL, NULL);
+retVal |= UA_Server_addReference(server, UA_NODEID_NUMERIC(ns[0], 2034), UA_NODEID_NUMERIC(ns[0], 45), UA_EXPANDEDNODEID_NUMERIC(ns[0], 58), false);
+return retVal;
+}
+
+static UA_StatusCode function_ua_namespace0_39_finish(UA_Server *server, UA_UInt16* ns) {
+
+return UA_Server_addNode_finish(server,
+UA_NODEID_NUMERIC(ns[0], 2034)
+);
+}
+
+/* ServerRedundancy - ns=0;i=2296 */
+
+static UA_StatusCode function_ua_namespace0_40_begin(UA_Server *server, UA_UInt16* ns) {
+
+UA_StatusCode retVal = UA_STATUSCODE_GOOD;
+UA_ObjectAttributes attr = UA_ObjectAttributes_default;
+attr.displayName = UA_LOCALIZEDTEXT("", "ServerRedundancy");
+attr.description = UA_LOCALIZEDTEXT("", "Describes the redundancy capabilities of the server.");
+attr.writeMask = 0;
+attr.userWriteMask = 0;
+retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_OBJECT,
+UA_NODEID_NUMERIC(ns[0], 2296),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_QUALIFIEDNAME(ns[0], "ServerRedundancy"),
+UA_NODEID_NUMERIC(ns[0], 2034),
+(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_OBJECTATTRIBUTES],NULL, NULL);
+retVal |= UA_Server_addReference(server, UA_NODEID_NUMERIC(ns[0], 2296), UA_NODEID_NUMERIC(ns[0], 47), UA_EXPANDEDNODEID_NUMERIC(ns[0], 2253), false);
+return retVal;
+}
+
+static UA_StatusCode function_ua_namespace0_40_finish(UA_Server *server, UA_UInt16* ns) {
+
+return UA_Server_addNode_finish(server,
+UA_NODEID_NUMERIC(ns[0], 2296)
+);
+}
+
+/* PropertyType - ns=0;i=68 */
+
+static UA_StatusCode function_ua_namespace0_41_begin(UA_Server *server, UA_UInt16* ns) {
+
+UA_StatusCode retVal = UA_STATUSCODE_GOOD;
+UA_VariableTypeAttributes attr = UA_VariableTypeAttributes_default;
+attr.valueRank = (UA_Int32)-2;
+attr.dataType = UA_NODEID_NUMERIC(ns[0], 24);
+attr.displayName = UA_LOCALIZEDTEXT("", "PropertyType");
+attr.description = UA_LOCALIZEDTEXT("", "The type for variable that represents a property of another node.");
+attr.writeMask = 0;
+attr.userWriteMask = 0;
+retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_VARIABLETYPE,
+UA_NODEID_NUMERIC(ns[0], 68),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_QUALIFIEDNAME(ns[0], "PropertyType"),
+UA_NODEID_NUMERIC(ns[0], 62),
+(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_VARIABLETYPEATTRIBUTES],NULL, NULL);
+retVal |= UA_Server_addReference(server, UA_NODEID_NUMERIC(ns[0], 68), UA_NODEID_NUMERIC(ns[0], 45), UA_EXPANDEDNODEID_NUMERIC(ns[0], 62), false);
+return retVal;
+}
+
+static UA_StatusCode function_ua_namespace0_41_finish(UA_Server *server, UA_UInt16* ns) {
+
+return UA_Server_addNode_finish(server,
+UA_NODEID_NUMERIC(ns[0], 68)
+);
+}
+
+/* MaxBrowseContinuationPoints - ns=0;i=2735 */
+
+static UA_StatusCode function_ua_namespace0_42_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.dataType = UA_NODEID_NUMERIC(ns[0], 5);
+UA_Variant_setScalar(&attr.value, NULL, &UA_TYPES[UA_TYPES_UINT16]);
+attr.displayName = UA_LOCALIZEDTEXT("", "MaxBrowseContinuationPoints");
+attr.description = UA_LOCALIZEDTEXT("", "The maximum number of continuation points for Browse operations per session.");
+attr.writeMask = 0;
+attr.userWriteMask = 0;
+retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_VARIABLE,
+UA_NODEID_NUMERIC(ns[0], 2735),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_QUALIFIEDNAME(ns[0], "MaxBrowseContinuationPoints"),
+UA_NODEID_NUMERIC(ns[0], 68),
+(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
+retVal |= UA_Server_addReference(server, UA_NODEID_NUMERIC(ns[0], 2735), UA_NODEID_NUMERIC(ns[0], 46), UA_EXPANDEDNODEID_NUMERIC(ns[0], 2268), false);
+return retVal;
+}
+
+static UA_StatusCode function_ua_namespace0_42_finish(UA_Server *server, UA_UInt16* ns) {
+
+return UA_Server_addNode_finish(server,
+UA_NODEID_NUMERIC(ns[0], 2735)
+);
+}
+
+/* MaxNodesPerBrowse - ns=0;i=11710 */
+
+static UA_StatusCode function_ua_namespace0_43_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.dataType = UA_NODEID_NUMERIC(ns[0], 7);
+UA_Variant_setScalar(&attr.value, NULL, &UA_TYPES[UA_TYPES_UINT32]);
+attr.displayName = UA_LOCALIZEDTEXT("", "MaxNodesPerBrowse");
+attr.description = UA_LOCALIZEDTEXT("", "The maximum number of operations in a single Browse request.");
+attr.writeMask = 0;
+attr.userWriteMask = 0;
+retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_VARIABLE,
+UA_NODEID_NUMERIC(ns[0], 11710),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_QUALIFIEDNAME(ns[0], "MaxNodesPerBrowse"),
+UA_NODEID_NUMERIC(ns[0], 68),
+(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
+retVal |= UA_Server_addReference(server, UA_NODEID_NUMERIC(ns[0], 11710), UA_NODEID_NUMERIC(ns[0], 46), UA_EXPANDEDNODEID_NUMERIC(ns[0], 11704), false);
+return retVal;
+}
+
+static UA_StatusCode function_ua_namespace0_43_finish(UA_Server *server, UA_UInt16* ns) {
+
+return UA_Server_addNode_finish(server,
+UA_NODEID_NUMERIC(ns[0], 11710)
+);
+}
+
+/* MaxNodesPerWrite - ns=0;i=11707 */
+
+static UA_StatusCode function_ua_namespace0_44_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.dataType = UA_NODEID_NUMERIC(ns[0], 7);
+UA_Variant_setScalar(&attr.value, NULL, &UA_TYPES[UA_TYPES_UINT32]);
+attr.displayName = UA_LOCALIZEDTEXT("", "MaxNodesPerWrite");
+attr.description = UA_LOCALIZEDTEXT("", "The maximum number of operations in a single Write request.");
+attr.writeMask = 0;
+attr.userWriteMask = 0;
+retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_VARIABLE,
+UA_NODEID_NUMERIC(ns[0], 11707),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_QUALIFIEDNAME(ns[0], "MaxNodesPerWrite"),
+UA_NODEID_NUMERIC(ns[0], 68),
+(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
+retVal |= UA_Server_addReference(server, UA_NODEID_NUMERIC(ns[0], 11707), UA_NODEID_NUMERIC(ns[0], 46), UA_EXPANDEDNODEID_NUMERIC(ns[0], 11704), false);
+return retVal;
+}
+
+static UA_StatusCode function_ua_namespace0_44_finish(UA_Server *server, UA_UInt16* ns) {
+
+return UA_Server_addNode_finish(server,
+UA_NODEID_NUMERIC(ns[0], 11707)
+);
+}
+
+/* Auditing - ns=0;i=2994 */
+
+static UA_StatusCode function_ua_namespace0_45_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.dataType = UA_NODEID_NUMERIC(ns[0], 1);
+UA_Variant_setScalar(&attr.value, NULL, &UA_TYPES[UA_TYPES_BOOLEAN]);
+attr.displayName = UA_LOCALIZEDTEXT("", "Auditing");
+attr.description = UA_LOCALIZEDTEXT("", "A flag indicating whether the server is currently generating audit events.");
+attr.writeMask = 0;
+attr.userWriteMask = 0;
+retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_VARIABLE,
+UA_NODEID_NUMERIC(ns[0], 2994),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_QUALIFIEDNAME(ns[0], "Auditing"),
+UA_NODEID_NUMERIC(ns[0], 68),
+(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
+retVal |= UA_Server_addReference(server, UA_NODEID_NUMERIC(ns[0], 2994), UA_NODEID_NUMERIC(ns[0], 46), UA_EXPANDEDNODEID_NUMERIC(ns[0], 2253), false);
+return retVal;
+}
+
+static UA_StatusCode function_ua_namespace0_45_finish(UA_Server *server, UA_UInt16* ns) {
+
+return UA_Server_addNode_finish(server,
+UA_NODEID_NUMERIC(ns[0], 2994)
+);
+}
+
+/* MaxNodesPerRead - ns=0;i=11565 */
+
+static UA_StatusCode function_ua_namespace0_46_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.dataType = UA_NODEID_NUMERIC(ns[0], 7);
+UA_Variant_setScalar(&attr.value, NULL, &UA_TYPES[UA_TYPES_UINT32]);
+attr.displayName = UA_LOCALIZEDTEXT("", "MaxNodesPerRead");
+attr.description = UA_LOCALIZEDTEXT("", "The maximum number of operations in a single Read request.");
+attr.writeMask = 0;
+attr.userWriteMask = 0;
+retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_VARIABLE,
+UA_NODEID_NUMERIC(ns[0], 11565),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_QUALIFIEDNAME(ns[0], "MaxNodesPerRead"),
+UA_NODEID_NUMERIC(ns[0], 68),
+(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
+retVal |= UA_Server_addReference(server, UA_NODEID_NUMERIC(ns[0], 11565), UA_NODEID_NUMERIC(ns[0], 46), UA_EXPANDEDNODEID_NUMERIC(ns[0], 11564), false);
+return retVal;
+}
+
+static UA_StatusCode function_ua_namespace0_46_finish(UA_Server *server, UA_UInt16* ns) {
+
+return UA_Server_addNode_finish(server,
+UA_NODEID_NUMERIC(ns[0], 11565)
+);
+}
+
+/* MaxNodesPerWrite - ns=0;i=11567 */
+
+static UA_StatusCode function_ua_namespace0_47_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.dataType = UA_NODEID_NUMERIC(ns[0], 7);
+UA_Variant_setScalar(&attr.value, NULL, &UA_TYPES[UA_TYPES_UINT32]);
+attr.displayName = UA_LOCALIZEDTEXT("", "MaxNodesPerWrite");
+attr.description = UA_LOCALIZEDTEXT("", "The maximum number of operations in a single Write request.");
+attr.writeMask = 0;
+attr.userWriteMask = 0;
+retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_VARIABLE,
+UA_NODEID_NUMERIC(ns[0], 11567),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_QUALIFIEDNAME(ns[0], "MaxNodesPerWrite"),
+UA_NODEID_NUMERIC(ns[0], 68),
+(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
+retVal |= UA_Server_addReference(server, UA_NODEID_NUMERIC(ns[0], 11567), UA_NODEID_NUMERIC(ns[0], 46), UA_EXPANDEDNODEID_NUMERIC(ns[0], 11564), false);
+return retVal;
+}
+
+static UA_StatusCode function_ua_namespace0_47_finish(UA_Server *server, UA_UInt16* ns) {
+
+return UA_Server_addNode_finish(server,
+UA_NODEID_NUMERIC(ns[0], 11567)
+);
+}
+
+/* RedundancySupport - ns=0;i=2035 */
+
+static UA_StatusCode function_ua_namespace0_48_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.dataType = UA_NODEID_NUMERIC(ns[0], 851);
+UA_Variant_setScalar(&attr.value, NULL, &UA_TYPES[UA_TYPES_REDUNDANCYSUPPORT]);
+attr.displayName = UA_LOCALIZEDTEXT("", "RedundancySupport");
+attr.description = UA_LOCALIZEDTEXT("", "Indicates what style of redundancy is supported by the server.");
+attr.writeMask = 0;
+attr.userWriteMask = 0;
+retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_VARIABLE,
+UA_NODEID_NUMERIC(ns[0], 2035),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_QUALIFIEDNAME(ns[0], "RedundancySupport"),
+UA_NODEID_NUMERIC(ns[0], 68),
+(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
+retVal |= UA_Server_addReference(server, UA_NODEID_NUMERIC(ns[0], 2035), UA_NODEID_NUMERIC(ns[0], 46), UA_EXPANDEDNODEID_NUMERIC(ns[0], 2034), false);
+return retVal;
+}
+
+static UA_StatusCode function_ua_namespace0_48_finish(UA_Server *server, UA_UInt16* ns) {
+
+return UA_Server_addNode_finish(server,
+UA_NODEID_NUMERIC(ns[0], 2035)
+);
+}
+
+/* MaxNodesPerMethodCall - ns=0;i=11569 */
+
+static UA_StatusCode function_ua_namespace0_49_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.dataType = UA_NODEID_NUMERIC(ns[0], 7);
+UA_Variant_setScalar(&attr.value, NULL, &UA_TYPES[UA_TYPES_UINT32]);
+attr.displayName = UA_LOCALIZEDTEXT("", "MaxNodesPerMethodCall");
+attr.description = UA_LOCALIZEDTEXT("", "The maximum number of operations in a single Call request.");
+attr.writeMask = 0;
+attr.userWriteMask = 0;
+retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_VARIABLE,
+UA_NODEID_NUMERIC(ns[0], 11569),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_QUALIFIEDNAME(ns[0], "MaxNodesPerMethodCall"),
+UA_NODEID_NUMERIC(ns[0], 68),
+(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
+retVal |= UA_Server_addReference(server, UA_NODEID_NUMERIC(ns[0], 11569), UA_NODEID_NUMERIC(ns[0], 46), UA_EXPANDEDNODEID_NUMERIC(ns[0], 11564), false);
+return retVal;
+}
+
+static UA_StatusCode function_ua_namespace0_49_finish(UA_Server *server, UA_UInt16* ns) {
+
+return UA_Server_addNode_finish(server,
+UA_NODEID_NUMERIC(ns[0], 11569)
+);
+}
+
+/* MaxNodesPerMethodCall - ns=0;i=11709 */
+
+static UA_StatusCode function_ua_namespace0_50_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.dataType = UA_NODEID_NUMERIC(ns[0], 7);
+UA_Variant_setScalar(&attr.value, NULL, &UA_TYPES[UA_TYPES_UINT32]);
+attr.displayName = UA_LOCALIZEDTEXT("", "MaxNodesPerMethodCall");
+attr.description = UA_LOCALIZEDTEXT("", "The maximum number of operations in a single Call request.");
+attr.writeMask = 0;
+attr.userWriteMask = 0;
+retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_VARIABLE,
+UA_NODEID_NUMERIC(ns[0], 11709),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_QUALIFIEDNAME(ns[0], "MaxNodesPerMethodCall"),
+UA_NODEID_NUMERIC(ns[0], 68),
+(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
+retVal |= UA_Server_addReference(server, UA_NODEID_NUMERIC(ns[0], 11709), UA_NODEID_NUMERIC(ns[0], 46), UA_EXPANDEDNODEID_NUMERIC(ns[0], 11704), false);
+return retVal;
+}
+
+static UA_StatusCode function_ua_namespace0_50_finish(UA_Server *server, UA_UInt16* ns) {
+
+return UA_Server_addNode_finish(server,
+UA_NODEID_NUMERIC(ns[0], 11709)
+);
+}
+
+/* NamespaceArray - ns=0;i=2255 */
+
+static UA_StatusCode function_ua_namespace0_51_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;
+attr.arrayDimensions = (UA_UInt32 *)UA_Array_new(1, &UA_TYPES[UA_TYPES_UINT32]);
+if (!attr.arrayDimensions) return UA_STATUSCODE_BADOUTOFMEMORY;
+attr.arrayDimensions[0] = 0;
+attr.dataType = UA_NODEID_NUMERIC(ns[0], 12);
+UA_Variant_setArray(&attr.value, NULL, (UA_Int32) 0, &UA_TYPES[UA_TYPES_STRING]);
+attr.displayName = UA_LOCALIZEDTEXT("", "NamespaceArray");
+attr.description = UA_LOCALIZEDTEXT("", "The list of namespace URIs used by the server.");
+attr.writeMask = 0;
+attr.userWriteMask = 0;
+retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_VARIABLE,
+UA_NODEID_NUMERIC(ns[0], 2255),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_QUALIFIEDNAME(ns[0], "NamespaceArray"),
+UA_NODEID_NUMERIC(ns[0], 68),
+(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
+UA_Array_delete(attr.arrayDimensions, 1, &UA_TYPES[UA_TYPES_UINT32]);
+retVal |= UA_Server_addReference(server, UA_NODEID_NUMERIC(ns[0], 2255), UA_NODEID_NUMERIC(ns[0], 46), UA_EXPANDEDNODEID_NUMERIC(ns[0], 2253), false);
+return retVal;
+}
+
+static UA_StatusCode function_ua_namespace0_51_finish(UA_Server *server, UA_UInt16* ns) {
+
+return UA_Server_addNode_finish(server,
+UA_NODEID_NUMERIC(ns[0], 2255)
+);
+}
+
+/* ServerArray - ns=0;i=2254 */
+
+static UA_StatusCode function_ua_namespace0_52_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;
+attr.arrayDimensions = (UA_UInt32 *)UA_Array_new(1, &UA_TYPES[UA_TYPES_UINT32]);
+if (!attr.arrayDimensions) return UA_STATUSCODE_BADOUTOFMEMORY;
+attr.arrayDimensions[0] = 0;
+attr.dataType = UA_NODEID_NUMERIC(ns[0], 12);
+UA_Variant_setArray(&attr.value, NULL, (UA_Int32) 0, &UA_TYPES[UA_TYPES_STRING]);
+attr.displayName = UA_LOCALIZEDTEXT("", "ServerArray");
+attr.description = UA_LOCALIZEDTEXT("", "The list of server URIs used by the server.");
+attr.writeMask = 0;
+attr.userWriteMask = 0;
+retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_VARIABLE,
+UA_NODEID_NUMERIC(ns[0], 2254),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_QUALIFIEDNAME(ns[0], "ServerArray"),
+UA_NODEID_NUMERIC(ns[0], 68),
+(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
+UA_Array_delete(attr.arrayDimensions, 1, &UA_TYPES[UA_TYPES_UINT32]);
+retVal |= UA_Server_addReference(server, UA_NODEID_NUMERIC(ns[0], 2254), UA_NODEID_NUMERIC(ns[0], 46), UA_EXPANDEDNODEID_NUMERIC(ns[0], 2253), false);
+return retVal;
+}
+
+static UA_StatusCode function_ua_namespace0_52_finish(UA_Server *server, UA_UInt16* ns) {
+
+return UA_Server_addNode_finish(server,
+UA_NODEID_NUMERIC(ns[0], 2254)
+);
+}
+
+/* MinSupportedSampleRate - ns=0;i=2272 */
+
+static UA_StatusCode function_ua_namespace0_53_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.dataType = UA_NODEID_NUMERIC(ns[0], 290);
+UA_Variant_setScalar(&attr.value, NULL, &UA_TYPES[UA_TYPES_DOUBLE]);
+attr.displayName = UA_LOCALIZEDTEXT("", "MinSupportedSampleRate");
+attr.description = UA_LOCALIZEDTEXT("", "The minimum sampling interval supported by the server.");
+attr.writeMask = 0;
+attr.userWriteMask = 0;
+retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_VARIABLE,
+UA_NODEID_NUMERIC(ns[0], 2272),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_QUALIFIEDNAME(ns[0], "MinSupportedSampleRate"),
+UA_NODEID_NUMERIC(ns[0], 68),
+(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
+retVal |= UA_Server_addReference(server, UA_NODEID_NUMERIC(ns[0], 2272), UA_NODEID_NUMERIC(ns[0], 46), UA_EXPANDEDNODEID_NUMERIC(ns[0], 2268), false);
+return retVal;
+}
+
+static UA_StatusCode function_ua_namespace0_53_finish(UA_Server *server, UA_UInt16* ns) {
+
+return UA_Server_addNode_finish(server,
+UA_NODEID_NUMERIC(ns[0], 2272)
+);
+}
+
+/* LocaleIdArray - ns=0;i=2271 */
+
+static UA_StatusCode function_ua_namespace0_54_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;
+attr.arrayDimensions = (UA_UInt32 *)UA_Array_new(1, &UA_TYPES[UA_TYPES_UINT32]);
+if (!attr.arrayDimensions) return UA_STATUSCODE_BADOUTOFMEMORY;
+attr.arrayDimensions[0] = 0;
+attr.dataType = UA_NODEID_NUMERIC(ns[0], 295);
+UA_Variant_setArray(&attr.value, NULL, (UA_Int32) 0, &UA_TYPES[UA_TYPES_STRING]);
+attr.displayName = UA_LOCALIZEDTEXT("", "LocaleIdArray");
+attr.description = UA_LOCALIZEDTEXT("", "A list of locales supported by the server.");
+attr.writeMask = 0;
+attr.userWriteMask = 0;
+retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_VARIABLE,
+UA_NODEID_NUMERIC(ns[0], 2271),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_QUALIFIEDNAME(ns[0], "LocaleIdArray"),
+UA_NODEID_NUMERIC(ns[0], 68),
+(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
+UA_Array_delete(attr.arrayDimensions, 1, &UA_TYPES[UA_TYPES_UINT32]);
+retVal |= UA_Server_addReference(server, UA_NODEID_NUMERIC(ns[0], 2271), UA_NODEID_NUMERIC(ns[0], 46), UA_EXPANDEDNODEID_NUMERIC(ns[0], 2268), false);
+return retVal;
+}
+
+static UA_StatusCode function_ua_namespace0_54_finish(UA_Server *server, UA_UInt16* ns) {
+
+return UA_Server_addNode_finish(server,
+UA_NODEID_NUMERIC(ns[0], 2271)
+);
+}
+
+/* EnumValues - ns=0;i=12169 */
+
+static UA_StatusCode function_ua_namespace0_55_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;
+attr.arrayDimensions = (UA_UInt32 *)UA_Array_new(1, &UA_TYPES[UA_TYPES_UINT32]);
+if (!attr.arrayDimensions) return UA_STATUSCODE_BADOUTOFMEMORY;
+attr.arrayDimensions[0] = 0;
+attr.dataType = UA_NODEID_NUMERIC(ns[0], 7594);
+
+struct {
+ UA_Int64 Value;
+ UA_LocalizedText DisplayName;
+ UA_LocalizedText Description;
+} variablenode_ns_0_i_12169_EnumValueType_0_0_struct;
+UA_ExtensionObject *variablenode_ns_0_i_12169_EnumValueType_0_0 = UA_ExtensionObject_new();
+if (!variablenode_ns_0_i_12169_EnumValueType_0_0) return UA_STATUSCODE_BADOUTOFMEMORY;
+variablenode_ns_0_i_12169_EnumValueType_0_0_struct.Value = (UA_Int64) 1;
+variablenode_ns_0_i_12169_EnumValueType_0_0_struct.DisplayName = UA_LOCALIZEDTEXT("", "Mandatory");
+variablenode_ns_0_i_12169_EnumValueType_0_0_struct.Description = UA_LOCALIZEDTEXT("", "The BrowseName must appear in all instances of the type.");
+variablenode_ns_0_i_12169_EnumValueType_0_0->encoding = UA_EXTENSIONOBJECT_ENCODED_BYTESTRING;
+variablenode_ns_0_i_12169_EnumValueType_0_0->content.encoded.typeId = UA_NODEID_NUMERIC(0, 8251);
+retVal |= UA_ByteString_allocBuffer(&variablenode_ns_0_i_12169_EnumValueType_0_0->content.encoded.body, 65000);
+UA_Byte *posvariablenode_ns_0_i_12169_EnumValueType_0_0 = variablenode_ns_0_i_12169_EnumValueType_0_0->content.encoded.body.data;
+const UA_Byte *endvariablenode_ns_0_i_12169_EnumValueType_0_0 = &variablenode_ns_0_i_12169_EnumValueType_0_0->content.encoded.body.data[65000];
+{
+retVal |= UA_encodeBinary(&variablenode_ns_0_i_12169_EnumValueType_0_0_struct.Value, &UA_TYPES[UA_TYPES_INT64], &posvariablenode_ns_0_i_12169_EnumValueType_0_0, &endvariablenode_ns_0_i_12169_EnumValueType_0_0, NULL, NULL);
+retVal |= UA_encodeBinary(&variablenode_ns_0_i_12169_EnumValueType_0_0_struct.DisplayName, &UA_TYPES[UA_TYPES_LOCALIZEDTEXT], &posvariablenode_ns_0_i_12169_EnumValueType_0_0, &endvariablenode_ns_0_i_12169_EnumValueType_0_0, NULL, NULL);
+retVal |= UA_encodeBinary(&variablenode_ns_0_i_12169_EnumValueType_0_0_struct.Description, &UA_TYPES[UA_TYPES_LOCALIZEDTEXT], &posvariablenode_ns_0_i_12169_EnumValueType_0_0, &endvariablenode_ns_0_i_12169_EnumValueType_0_0, NULL, NULL);
+}
+size_t variablenode_ns_0_i_12169_EnumValueType_0_0_encOffset = (uintptr_t)(posvariablenode_ns_0_i_12169_EnumValueType_0_0-variablenode_ns_0_i_12169_EnumValueType_0_0->content.encoded.body.data);
+variablenode_ns_0_i_12169_EnumValueType_0_0->content.encoded.body.length = variablenode_ns_0_i_12169_EnumValueType_0_0_encOffset;
+UA_Byte *variablenode_ns_0_i_12169_EnumValueType_0_0_newBody = (UA_Byte *) UA_malloc(variablenode_ns_0_i_12169_EnumValueType_0_0_encOffset);
+if (!variablenode_ns_0_i_12169_EnumValueType_0_0_newBody) return UA_STATUSCODE_BADOUTOFMEMORY;
+memcpy(variablenode_ns_0_i_12169_EnumValueType_0_0_newBody, variablenode_ns_0_i_12169_EnumValueType_0_0->content.encoded.body.data, variablenode_ns_0_i_12169_EnumValueType_0_0_encOffset);
+UA_Byte *variablenode_ns_0_i_12169_EnumValueType_0_0_oldBody = variablenode_ns_0_i_12169_EnumValueType_0_0->content.encoded.body.data;
+variablenode_ns_0_i_12169_EnumValueType_0_0->content.encoded.body.data = variablenode_ns_0_i_12169_EnumValueType_0_0_newBody;
+UA_free(variablenode_ns_0_i_12169_EnumValueType_0_0_oldBody);
+
+
+struct {
+ UA_Int64 Value;
+ UA_LocalizedText DisplayName;
+ UA_LocalizedText Description;
+} variablenode_ns_0_i_12169_EnumValueType_1_0_struct;
+UA_ExtensionObject *variablenode_ns_0_i_12169_EnumValueType_1_0 = UA_ExtensionObject_new();
+if (!variablenode_ns_0_i_12169_EnumValueType_1_0) return UA_STATUSCODE_BADOUTOFMEMORY;
+variablenode_ns_0_i_12169_EnumValueType_1_0_struct.Value = (UA_Int64) 2;
+variablenode_ns_0_i_12169_EnumValueType_1_0_struct.DisplayName = UA_LOCALIZEDTEXT("", "Optional");
+variablenode_ns_0_i_12169_EnumValueType_1_0_struct.Description = UA_LOCALIZEDTEXT("", "The BrowseName may appear in an instance of the type.");
+variablenode_ns_0_i_12169_EnumValueType_1_0->encoding = UA_EXTENSIONOBJECT_ENCODED_BYTESTRING;
+variablenode_ns_0_i_12169_EnumValueType_1_0->content.encoded.typeId = UA_NODEID_NUMERIC(0, 8251);
+retVal |= UA_ByteString_allocBuffer(&variablenode_ns_0_i_12169_EnumValueType_1_0->content.encoded.body, 65000);
+UA_Byte *posvariablenode_ns_0_i_12169_EnumValueType_1_0 = variablenode_ns_0_i_12169_EnumValueType_1_0->content.encoded.body.data;
+const UA_Byte *endvariablenode_ns_0_i_12169_EnumValueType_1_0 = &variablenode_ns_0_i_12169_EnumValueType_1_0->content.encoded.body.data[65000];
+{
+retVal |= UA_encodeBinary(&variablenode_ns_0_i_12169_EnumValueType_1_0_struct.Value, &UA_TYPES[UA_TYPES_INT64], &posvariablenode_ns_0_i_12169_EnumValueType_1_0, &endvariablenode_ns_0_i_12169_EnumValueType_1_0, NULL, NULL);
+retVal |= UA_encodeBinary(&variablenode_ns_0_i_12169_EnumValueType_1_0_struct.DisplayName, &UA_TYPES[UA_TYPES_LOCALIZEDTEXT], &posvariablenode_ns_0_i_12169_EnumValueType_1_0, &endvariablenode_ns_0_i_12169_EnumValueType_1_0, NULL, NULL);
+retVal |= UA_encodeBinary(&variablenode_ns_0_i_12169_EnumValueType_1_0_struct.Description, &UA_TYPES[UA_TYPES_LOCALIZEDTEXT], &posvariablenode_ns_0_i_12169_EnumValueType_1_0, &endvariablenode_ns_0_i_12169_EnumValueType_1_0, NULL, NULL);
+}
+size_t variablenode_ns_0_i_12169_EnumValueType_1_0_encOffset = (uintptr_t)(posvariablenode_ns_0_i_12169_EnumValueType_1_0-variablenode_ns_0_i_12169_EnumValueType_1_0->content.encoded.body.data);
+variablenode_ns_0_i_12169_EnumValueType_1_0->content.encoded.body.length = variablenode_ns_0_i_12169_EnumValueType_1_0_encOffset;
+UA_Byte *variablenode_ns_0_i_12169_EnumValueType_1_0_newBody = (UA_Byte *) UA_malloc(variablenode_ns_0_i_12169_EnumValueType_1_0_encOffset);
+if (!variablenode_ns_0_i_12169_EnumValueType_1_0_newBody) return UA_STATUSCODE_BADOUTOFMEMORY;
+memcpy(variablenode_ns_0_i_12169_EnumValueType_1_0_newBody, variablenode_ns_0_i_12169_EnumValueType_1_0->content.encoded.body.data, variablenode_ns_0_i_12169_EnumValueType_1_0_encOffset);
+UA_Byte *variablenode_ns_0_i_12169_EnumValueType_1_0_oldBody = variablenode_ns_0_i_12169_EnumValueType_1_0->content.encoded.body.data;
+variablenode_ns_0_i_12169_EnumValueType_1_0->content.encoded.body.data = variablenode_ns_0_i_12169_EnumValueType_1_0_newBody;
+UA_free(variablenode_ns_0_i_12169_EnumValueType_1_0_oldBody);
+
+
+struct {
+ UA_Int64 Value;
+ UA_LocalizedText DisplayName;
+ UA_LocalizedText Description;
+} variablenode_ns_0_i_12169_EnumValueType_2_0_struct;
+UA_ExtensionObject *variablenode_ns_0_i_12169_EnumValueType_2_0 = UA_ExtensionObject_new();
+if (!variablenode_ns_0_i_12169_EnumValueType_2_0) return UA_STATUSCODE_BADOUTOFMEMORY;
+variablenode_ns_0_i_12169_EnumValueType_2_0_struct.Value = (UA_Int64) 3;
+variablenode_ns_0_i_12169_EnumValueType_2_0_struct.DisplayName = UA_LOCALIZEDTEXT("", "Constraint");
+variablenode_ns_0_i_12169_EnumValueType_2_0_struct.Description = UA_LOCALIZEDTEXT("", "The modelling rule defines a constraint and the BrowseName is not used in an instance of the type.");
+variablenode_ns_0_i_12169_EnumValueType_2_0->encoding = UA_EXTENSIONOBJECT_ENCODED_BYTESTRING;
+variablenode_ns_0_i_12169_EnumValueType_2_0->content.encoded.typeId = UA_NODEID_NUMERIC(0, 8251);
+retVal |= UA_ByteString_allocBuffer(&variablenode_ns_0_i_12169_EnumValueType_2_0->content.encoded.body, 65000);
+UA_Byte *posvariablenode_ns_0_i_12169_EnumValueType_2_0 = variablenode_ns_0_i_12169_EnumValueType_2_0->content.encoded.body.data;
+const UA_Byte *endvariablenode_ns_0_i_12169_EnumValueType_2_0 = &variablenode_ns_0_i_12169_EnumValueType_2_0->content.encoded.body.data[65000];
+{
+retVal |= UA_encodeBinary(&variablenode_ns_0_i_12169_EnumValueType_2_0_struct.Value, &UA_TYPES[UA_TYPES_INT64], &posvariablenode_ns_0_i_12169_EnumValueType_2_0, &endvariablenode_ns_0_i_12169_EnumValueType_2_0, NULL, NULL);
+retVal |= UA_encodeBinary(&variablenode_ns_0_i_12169_EnumValueType_2_0_struct.DisplayName, &UA_TYPES[UA_TYPES_LOCALIZEDTEXT], &posvariablenode_ns_0_i_12169_EnumValueType_2_0, &endvariablenode_ns_0_i_12169_EnumValueType_2_0, NULL, NULL);
+retVal |= UA_encodeBinary(&variablenode_ns_0_i_12169_EnumValueType_2_0_struct.Description, &UA_TYPES[UA_TYPES_LOCALIZEDTEXT], &posvariablenode_ns_0_i_12169_EnumValueType_2_0, &endvariablenode_ns_0_i_12169_EnumValueType_2_0, NULL, NULL);
+}
+size_t variablenode_ns_0_i_12169_EnumValueType_2_0_encOffset = (uintptr_t)(posvariablenode_ns_0_i_12169_EnumValueType_2_0-variablenode_ns_0_i_12169_EnumValueType_2_0->content.encoded.body.data);
+variablenode_ns_0_i_12169_EnumValueType_2_0->content.encoded.body.length = variablenode_ns_0_i_12169_EnumValueType_2_0_encOffset;
+UA_Byte *variablenode_ns_0_i_12169_EnumValueType_2_0_newBody = (UA_Byte *) UA_malloc(variablenode_ns_0_i_12169_EnumValueType_2_0_encOffset);
+if (!variablenode_ns_0_i_12169_EnumValueType_2_0_newBody) return UA_STATUSCODE_BADOUTOFMEMORY;
+memcpy(variablenode_ns_0_i_12169_EnumValueType_2_0_newBody, variablenode_ns_0_i_12169_EnumValueType_2_0->content.encoded.body.data, variablenode_ns_0_i_12169_EnumValueType_2_0_encOffset);
+UA_Byte *variablenode_ns_0_i_12169_EnumValueType_2_0_oldBody = variablenode_ns_0_i_12169_EnumValueType_2_0->content.encoded.body.data;
+variablenode_ns_0_i_12169_EnumValueType_2_0->content.encoded.body.data = variablenode_ns_0_i_12169_EnumValueType_2_0_newBody;
+UA_free(variablenode_ns_0_i_12169_EnumValueType_2_0_oldBody);
+
+UA_ExtensionObject variablenode_ns_0_i_12169_variant_DataContents[3];
+variablenode_ns_0_i_12169_variant_DataContents[0] = *variablenode_ns_0_i_12169_EnumValueType_0_0;
+variablenode_ns_0_i_12169_variant_DataContents[1] = *variablenode_ns_0_i_12169_EnumValueType_1_0;
+variablenode_ns_0_i_12169_variant_DataContents[2] = *variablenode_ns_0_i_12169_EnumValueType_2_0;
+UA_Variant_setArray(&attr.value, &variablenode_ns_0_i_12169_variant_DataContents, (UA_Int32) 3, &UA_TYPES[UA_TYPES_EXTENSIONOBJECT]);
+attr.displayName = UA_LOCALIZEDTEXT("", "EnumValues");
+attr.description = UA_LOCALIZEDTEXT("", "");
+attr.writeMask = 0;
+attr.userWriteMask = 0;
+retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_VARIABLE,
+UA_NODEID_NUMERIC(ns[0], 12169),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_QUALIFIEDNAME(ns[0], "EnumValues"),
+UA_NODEID_NUMERIC(ns[0], 68),
+(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
+UA_Array_delete(attr.arrayDimensions, 1, &UA_TYPES[UA_TYPES_UINT32]);
+
+UA_ExtensionObject_delete(variablenode_ns_0_i_12169_EnumValueType_0_0);
+
+UA_ExtensionObject_delete(variablenode_ns_0_i_12169_EnumValueType_1_0);
+
+UA_ExtensionObject_delete(variablenode_ns_0_i_12169_EnumValueType_2_0);
+retVal |= UA_Server_addReference(server, UA_NODEID_NUMERIC(ns[0], 12169), UA_NODEID_NUMERIC(ns[0], 46), UA_EXPANDEDNODEID_NUMERIC(ns[0], 120), false);
+return retVal;
+}
+
+static UA_StatusCode function_ua_namespace0_55_finish(UA_Server *server, UA_UInt16* ns) {
+
+return UA_Server_addNode_finish(server,
+UA_NODEID_NUMERIC(ns[0], 12169)
+);
+}
+
+/* MaxNodesPerTranslateBrowsePathsToNodeIds - ns=0;i=11712 */
+
+static UA_StatusCode function_ua_namespace0_56_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.dataType = UA_NODEID_NUMERIC(ns[0], 7);
+UA_Variant_setScalar(&attr.value, NULL, &UA_TYPES[UA_TYPES_UINT32]);
+attr.displayName = UA_LOCALIZEDTEXT("", "MaxNodesPerTranslateBrowsePathsToNodeIds");
+attr.description = UA_LOCALIZEDTEXT("", "The maximum number of operations in a single TranslateBrowsePathsToNodeIds request.");
+attr.writeMask = 0;
+attr.userWriteMask = 0;
+retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_VARIABLE,
+UA_NODEID_NUMERIC(ns[0], 11712),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_QUALIFIEDNAME(ns[0], "MaxNodesPerTranslateBrowsePathsToNodeIds"),
+UA_NODEID_NUMERIC(ns[0], 68),
+(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
+retVal |= UA_Server_addReference(server, UA_NODEID_NUMERIC(ns[0], 11712), UA_NODEID_NUMERIC(ns[0], 46), UA_EXPANDEDNODEID_NUMERIC(ns[0], 11704), false);
+return retVal;
+}
+
+static UA_StatusCode function_ua_namespace0_56_finish(UA_Server *server, UA_UInt16* ns) {
+
+return UA_Server_addNode_finish(server,
+UA_NODEID_NUMERIC(ns[0], 11712)
+);
+}
+
+/* MaxMonitoredItemsPerCall - ns=0;i=11574 */
+
+static UA_StatusCode function_ua_namespace0_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;
+attr.valueRank = -1;
+attr.dataType = UA_NODEID_NUMERIC(ns[0], 7);
+UA_Variant_setScalar(&attr.value, NULL, &UA_TYPES[UA_TYPES_UINT32]);
+attr.displayName = UA_LOCALIZEDTEXT("", "MaxMonitoredItemsPerCall");
+attr.description = UA_LOCALIZEDTEXT("", "The maximum number of operations in a single MonitoredItem related request.");
+attr.writeMask = 0;
+attr.userWriteMask = 0;
+retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_VARIABLE,
+UA_NODEID_NUMERIC(ns[0], 11574),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_QUALIFIEDNAME(ns[0], "MaxMonitoredItemsPerCall"),
+UA_NODEID_NUMERIC(ns[0], 68),
+(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
+retVal |= UA_Server_addReference(server, UA_NODEID_NUMERIC(ns[0], 11574), UA_NODEID_NUMERIC(ns[0], 46), UA_EXPANDEDNODEID_NUMERIC(ns[0], 11564), false);
+return retVal;
+}
+
+static UA_StatusCode function_ua_namespace0_57_finish(UA_Server *server, UA_UInt16* ns) {
+
+return UA_Server_addNode_finish(server,
+UA_NODEID_NUMERIC(ns[0], 11574)
+);
+}
+
+/* MaxNodesPerNodeManagement - ns=0;i=11573 */
+
+static UA_StatusCode function_ua_namespace0_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;
+attr.valueRank = -1;
+attr.dataType = UA_NODEID_NUMERIC(ns[0], 7);
+UA_Variant_setScalar(&attr.value, NULL, &UA_TYPES[UA_TYPES_UINT32]);
+attr.displayName = UA_LOCALIZEDTEXT("", "MaxNodesPerNodeManagement");
+attr.description = UA_LOCALIZEDTEXT("", "The maximum number of operations in a single AddNodes, AddReferences, DeleteNodes or DeleteReferences request.");
+attr.writeMask = 0;
+attr.userWriteMask = 0;
+retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_VARIABLE,
+UA_NODEID_NUMERIC(ns[0], 11573),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_QUALIFIEDNAME(ns[0], "MaxNodesPerNodeManagement"),
+UA_NODEID_NUMERIC(ns[0], 68),
+(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
+retVal |= UA_Server_addReference(server, UA_NODEID_NUMERIC(ns[0], 11573), UA_NODEID_NUMERIC(ns[0], 46), UA_EXPANDEDNODEID_NUMERIC(ns[0], 11564), false);
+return retVal;
+}
+
+static UA_StatusCode function_ua_namespace0_58_finish(UA_Server *server, UA_UInt16* ns) {
+
+return UA_Server_addNode_finish(server,
+UA_NODEID_NUMERIC(ns[0], 11573)
+);
+}
+
+/* MaxNodesPerTranslateBrowsePathsToNodeIds - ns=0;i=11572 */
+
+static UA_StatusCode function_ua_namespace0_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 = 1;
+attr.accessLevel = 1;
+attr.valueRank = -1;
+attr.dataType = UA_NODEID_NUMERIC(ns[0], 7);
+UA_Variant_setScalar(&attr.value, NULL, &UA_TYPES[UA_TYPES_UINT32]);
+attr.displayName = UA_LOCALIZEDTEXT("", "MaxNodesPerTranslateBrowsePathsToNodeIds");
+attr.description = UA_LOCALIZEDTEXT("", "The maximum number of operations in a single TranslateBrowsePathsToNodeIds request.");
+attr.writeMask = 0;
+attr.userWriteMask = 0;
+retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_VARIABLE,
+UA_NODEID_NUMERIC(ns[0], 11572),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_QUALIFIEDNAME(ns[0], "MaxNodesPerTranslateBrowsePathsToNodeIds"),
+UA_NODEID_NUMERIC(ns[0], 68),
+(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
+retVal |= UA_Server_addReference(server, UA_NODEID_NUMERIC(ns[0], 11572), UA_NODEID_NUMERIC(ns[0], 46), UA_EXPANDEDNODEID_NUMERIC(ns[0], 11564), false);
+return retVal;
+}
+
+static UA_StatusCode function_ua_namespace0_59_finish(UA_Server *server, UA_UInt16* ns) {
+
+return UA_Server_addNode_finish(server,
+UA_NODEID_NUMERIC(ns[0], 11572)
+);
+}
+
+/* MaxNodesPerRegisterNodes - ns=0;i=11571 */
+
+static UA_StatusCode function_ua_namespace0_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;
+attr.valueRank = -1;
+attr.dataType = UA_NODEID_NUMERIC(ns[0], 7);
+UA_Variant_setScalar(&attr.value, NULL, &UA_TYPES[UA_TYPES_UINT32]);
+attr.displayName = UA_LOCALIZEDTEXT("", "MaxNodesPerRegisterNodes");
+attr.description = UA_LOCALIZEDTEXT("", "The maximum number of operations in a single RegisterNodes request.");
+attr.writeMask = 0;
+attr.userWriteMask = 0;
+retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_VARIABLE,
+UA_NODEID_NUMERIC(ns[0], 11571),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_QUALIFIEDNAME(ns[0], "MaxNodesPerRegisterNodes"),
+UA_NODEID_NUMERIC(ns[0], 68),
+(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
+retVal |= UA_Server_addReference(server, UA_NODEID_NUMERIC(ns[0], 11571), UA_NODEID_NUMERIC(ns[0], 46), UA_EXPANDEDNODEID_NUMERIC(ns[0], 11564), false);
+return retVal;
+}
+
+static UA_StatusCode function_ua_namespace0_60_finish(UA_Server *server, UA_UInt16* ns) {
+
+return UA_Server_addNode_finish(server,
+UA_NODEID_NUMERIC(ns[0], 11571)
+);
+}
+
+/* MaxNodesPerBrowse - ns=0;i=11570 */
+
+static UA_StatusCode function_ua_namespace0_61_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.dataType = UA_NODEID_NUMERIC(ns[0], 7);
+UA_Variant_setScalar(&attr.value, NULL, &UA_TYPES[UA_TYPES_UINT32]);
+attr.displayName = UA_LOCALIZEDTEXT("", "MaxNodesPerBrowse");
+attr.description = UA_LOCALIZEDTEXT("", "The maximum number of operations in a single Browse request.");
+attr.writeMask = 0;
+attr.userWriteMask = 0;
+retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_VARIABLE,
+UA_NODEID_NUMERIC(ns[0], 11570),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_QUALIFIEDNAME(ns[0], "MaxNodesPerBrowse"),
+UA_NODEID_NUMERIC(ns[0], 68),
+(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
+retVal |= UA_Server_addReference(server, UA_NODEID_NUMERIC(ns[0], 11570), UA_NODEID_NUMERIC(ns[0], 46), UA_EXPANDEDNODEID_NUMERIC(ns[0], 11564), false);
+return retVal;
+}
+
+static UA_StatusCode function_ua_namespace0_61_finish(UA_Server *server, UA_UInt16* ns) {
+
+return UA_Server_addNode_finish(server,
+UA_NODEID_NUMERIC(ns[0], 11570)
+);
+}
+
+/* MaxNodesPerRead - ns=0;i=11705 */
+
+static UA_StatusCode function_ua_namespace0_62_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.dataType = UA_NODEID_NUMERIC(ns[0], 7);
+UA_Variant_setScalar(&attr.value, NULL, &UA_TYPES[UA_TYPES_UINT32]);
+attr.displayName = UA_LOCALIZEDTEXT("", "MaxNodesPerRead");
+attr.description = UA_LOCALIZEDTEXT("", "The maximum number of operations in a single Read request.");
+attr.writeMask = 0;
+attr.userWriteMask = 0;
+retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_VARIABLE,
+UA_NODEID_NUMERIC(ns[0], 11705),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_QUALIFIEDNAME(ns[0], "MaxNodesPerRead"),
+UA_NODEID_NUMERIC(ns[0], 68),
+(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
+retVal |= UA_Server_addReference(server, UA_NODEID_NUMERIC(ns[0], 11705), UA_NODEID_NUMERIC(ns[0], 46), UA_EXPANDEDNODEID_NUMERIC(ns[0], 11704), false);
+return retVal;
+}
+
+static UA_StatusCode function_ua_namespace0_62_finish(UA_Server *server, UA_UInt16* ns) {
+
+return UA_Server_addNode_finish(server,
+UA_NODEID_NUMERIC(ns[0], 11705)
+);
+}
+
+/* EnumStrings - ns=0;i=7611 */
+
+static UA_StatusCode function_ua_namespace0_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;
+attr.valueRank = 1;
+attr.arrayDimensionsSize = 1;
+attr.arrayDimensions = (UA_UInt32 *)UA_Array_new(1, &UA_TYPES[UA_TYPES_UINT32]);
+if (!attr.arrayDimensions) return UA_STATUSCODE_BADOUTOFMEMORY;
+attr.arrayDimensions[0] = 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.description = UA_LOCALIZEDTEXT("", "");
+attr.writeMask = 0;
+attr.userWriteMask = 0;
+retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_VARIABLE,
+UA_NODEID_NUMERIC(ns[0], 7611),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_QUALIFIEDNAME(ns[0], "EnumStrings"),
+UA_NODEID_NUMERIC(ns[0], 68),
+(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
+UA_Array_delete(attr.arrayDimensions, 1, &UA_TYPES[UA_TYPES_UINT32]);
+retVal |= UA_Server_addReference(server, UA_NODEID_NUMERIC(ns[0], 7611), UA_NODEID_NUMERIC(ns[0], 46), UA_EXPANDEDNODEID_NUMERIC(ns[0], 851), false);
+return retVal;
+}
+
+static UA_StatusCode function_ua_namespace0_63_finish(UA_Server *server, UA_UInt16* ns) {
+
+return UA_Server_addNode_finish(server,
+UA_NODEID_NUMERIC(ns[0], 7611)
+);
+}
+
+/* ServerProfileArray - ns=0;i=2269 */
+
+static UA_StatusCode function_ua_namespace0_64_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;
+attr.arrayDimensions = (UA_UInt32 *)UA_Array_new(1, &UA_TYPES[UA_TYPES_UINT32]);
+if (!attr.arrayDimensions) return UA_STATUSCODE_BADOUTOFMEMORY;
+attr.arrayDimensions[0] = 0;
+attr.dataType = UA_NODEID_NUMERIC(ns[0], 12);
+UA_Variant_setArray(&attr.value, NULL, (UA_Int32) 0, &UA_TYPES[UA_TYPES_STRING]);
+attr.displayName = UA_LOCALIZEDTEXT("", "ServerProfileArray");
+attr.description = UA_LOCALIZEDTEXT("", "A list of profiles supported by the server.");
+attr.writeMask = 0;
+attr.userWriteMask = 0;
+retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_VARIABLE,
+UA_NODEID_NUMERIC(ns[0], 2269),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_QUALIFIEDNAME(ns[0], "ServerProfileArray"),
+UA_NODEID_NUMERIC(ns[0], 68),
+(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
+UA_Array_delete(attr.arrayDimensions, 1, &UA_TYPES[UA_TYPES_UINT32]);
+retVal |= UA_Server_addReference(server, UA_NODEID_NUMERIC(ns[0], 2269), UA_NODEID_NUMERIC(ns[0], 46), UA_EXPANDEDNODEID_NUMERIC(ns[0], 2268), false);
+return retVal;
+}
+
+static UA_StatusCode function_ua_namespace0_64_finish(UA_Server *server, UA_UInt16* ns) {
+
+return UA_Server_addNode_finish(server,
+UA_NODEID_NUMERIC(ns[0], 2269)
+);
+}
+
+/* MaxQueryContinuationPoints - ns=0;i=2736 */
+
+static UA_StatusCode function_ua_namespace0_65_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.dataType = UA_NODEID_NUMERIC(ns[0], 5);
+UA_Variant_setScalar(&attr.value, NULL, &UA_TYPES[UA_TYPES_UINT16]);
+attr.displayName = UA_LOCALIZEDTEXT("", "MaxQueryContinuationPoints");
+attr.description = UA_LOCALIZEDTEXT("", "The maximum number of continuation points for Query operations per session.");
+attr.writeMask = 0;
+attr.userWriteMask = 0;
+retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_VARIABLE,
+UA_NODEID_NUMERIC(ns[0], 2736),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_QUALIFIEDNAME(ns[0], "MaxQueryContinuationPoints"),
+UA_NODEID_NUMERIC(ns[0], 68),
+(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
+retVal |= UA_Server_addReference(server, UA_NODEID_NUMERIC(ns[0], 2736), UA_NODEID_NUMERIC(ns[0], 46), UA_EXPANDEDNODEID_NUMERIC(ns[0], 2268), false);
+return retVal;
+}
+
+static UA_StatusCode function_ua_namespace0_65_finish(UA_Server *server, UA_UInt16* ns) {
+
+return UA_Server_addNode_finish(server,
+UA_NODEID_NUMERIC(ns[0], 2736)
+);
+}
+
+/* MaxHistoryContinuationPoints - ns=0;i=2737 */
+
+static UA_StatusCode function_ua_namespace0_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.dataType = UA_NODEID_NUMERIC(ns[0], 5);
+UA_Variant_setScalar(&attr.value, NULL, &UA_TYPES[UA_TYPES_UINT16]);
+attr.displayName = UA_LOCALIZEDTEXT("", "MaxHistoryContinuationPoints");
+attr.description = UA_LOCALIZEDTEXT("", "The maximum number of continuation points for ReadHistory operations per session.");
+attr.writeMask = 0;
+attr.userWriteMask = 0;
+retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_VARIABLE,
+UA_NODEID_NUMERIC(ns[0], 2737),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_QUALIFIEDNAME(ns[0], "MaxHistoryContinuationPoints"),
+UA_NODEID_NUMERIC(ns[0], 68),
+(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
+retVal |= UA_Server_addReference(server, UA_NODEID_NUMERIC(ns[0], 2737), UA_NODEID_NUMERIC(ns[0], 46), UA_EXPANDEDNODEID_NUMERIC(ns[0], 2268), false);
+return retVal;
+}
+
+static UA_StatusCode function_ua_namespace0_66_finish(UA_Server *server, UA_UInt16* ns) {
+
+return UA_Server_addNode_finish(server,
+UA_NODEID_NUMERIC(ns[0], 2737)
+);
+}
+
+/* MaxNodesPerRegisterNodes - ns=0;i=11711 */
+
+static UA_StatusCode function_ua_namespace0_67_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.dataType = UA_NODEID_NUMERIC(ns[0], 7);
+UA_Variant_setScalar(&attr.value, NULL, &UA_TYPES[UA_TYPES_UINT32]);
+attr.displayName = UA_LOCALIZEDTEXT("", "MaxNodesPerRegisterNodes");
+attr.description = UA_LOCALIZEDTEXT("", "The maximum number of operations in a single RegisterNodes request.");
+attr.writeMask = 0;
+attr.userWriteMask = 0;
+retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_VARIABLE,
+UA_NODEID_NUMERIC(ns[0], 11711),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_QUALIFIEDNAME(ns[0], "MaxNodesPerRegisterNodes"),
+UA_NODEID_NUMERIC(ns[0], 68),
+(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
+retVal |= UA_Server_addReference(server, UA_NODEID_NUMERIC(ns[0], 11711), UA_NODEID_NUMERIC(ns[0], 46), UA_EXPANDEDNODEID_NUMERIC(ns[0], 11704), false);
+return retVal;
+}
+
+static UA_StatusCode function_ua_namespace0_67_finish(UA_Server *server, UA_UInt16* ns) {
+
+return UA_Server_addNode_finish(server,
+UA_NODEID_NUMERIC(ns[0], 11711)
+);
+}
+
+/* ServiceLevel - ns=0;i=2267 */
+
+static UA_StatusCode function_ua_namespace0_68_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.dataType = UA_NODEID_NUMERIC(ns[0], 3);
+UA_Variant_setScalar(&attr.value, NULL, &UA_TYPES[UA_TYPES_BYTE]);
+attr.displayName = UA_LOCALIZEDTEXT("", "ServiceLevel");
+attr.description = UA_LOCALIZEDTEXT("", "A value indicating the level of service the server can provide. 255 indicates the best.");
+attr.writeMask = 0;
+attr.userWriteMask = 0;
+retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_VARIABLE,
+UA_NODEID_NUMERIC(ns[0], 2267),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_QUALIFIEDNAME(ns[0], "ServiceLevel"),
+UA_NODEID_NUMERIC(ns[0], 68),
+(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
+retVal |= UA_Server_addReference(server, UA_NODEID_NUMERIC(ns[0], 2267), UA_NODEID_NUMERIC(ns[0], 46), UA_EXPANDEDNODEID_NUMERIC(ns[0], 2253), false);
+return retVal;
+}
+
+static UA_StatusCode function_ua_namespace0_68_finish(UA_Server *server, UA_UInt16* ns) {
+
+return UA_Server_addNode_finish(server,
+UA_NODEID_NUMERIC(ns[0], 2267)
+);
+}
+
+/* RedundancySupport - ns=0;i=3709 */
+
+static UA_StatusCode function_ua_namespace0_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;
+attr.valueRank = -1;
+attr.dataType = UA_NODEID_NUMERIC(ns[0], 851);
+UA_Variant_setScalar(&attr.value, NULL, &UA_TYPES[UA_TYPES_REDUNDANCYSUPPORT]);
+attr.displayName = UA_LOCALIZEDTEXT("", "RedundancySupport");
+attr.description = UA_LOCALIZEDTEXT("", "Indicates what style of redundancy is supported by the server.");
+attr.writeMask = 0;
+attr.userWriteMask = 0;
+retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_VARIABLE,
+UA_NODEID_NUMERIC(ns[0], 3709),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_QUALIFIEDNAME(ns[0], "RedundancySupport"),
+UA_NODEID_NUMERIC(ns[0], 68),
+(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
+retVal |= UA_Server_addReference(server, UA_NODEID_NUMERIC(ns[0], 3709), UA_NODEID_NUMERIC(ns[0], 46), UA_EXPANDEDNODEID_NUMERIC(ns[0], 2296), false);
+return retVal;
+}
+
+static UA_StatusCode function_ua_namespace0_69_finish(UA_Server *server, UA_UInt16* ns) {
+
+return UA_Server_addNode_finish(server,
+UA_NODEID_NUMERIC(ns[0], 3709)
+);
+}
+
+/* MaxMonitoredItemsPerCall - ns=0;i=11714 */
+
+static UA_StatusCode function_ua_namespace0_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;
+attr.valueRank = -1;
+attr.dataType = UA_NODEID_NUMERIC(ns[0], 7);
+UA_Variant_setScalar(&attr.value, NULL, &UA_TYPES[UA_TYPES_UINT32]);
+attr.displayName = UA_LOCALIZEDTEXT("", "MaxMonitoredItemsPerCall");
+attr.description = UA_LOCALIZEDTEXT("", "The maximum number of operations in a single MonitoredItem related request.");
+attr.writeMask = 0;
+attr.userWriteMask = 0;
+retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_VARIABLE,
+UA_NODEID_NUMERIC(ns[0], 11714),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_QUALIFIEDNAME(ns[0], "MaxMonitoredItemsPerCall"),
+UA_NODEID_NUMERIC(ns[0], 68),
+(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
+retVal |= UA_Server_addReference(server, UA_NODEID_NUMERIC(ns[0], 11714), UA_NODEID_NUMERIC(ns[0], 46), UA_EXPANDEDNODEID_NUMERIC(ns[0], 11704), false);
+return retVal;
+}
+
+static UA_StatusCode function_ua_namespace0_70_finish(UA_Server *server, UA_UInt16* ns) {
+
+return UA_Server_addNode_finish(server,
+UA_NODEID_NUMERIC(ns[0], 11714)
+);
+}
+
+/* MaxNodesPerNodeManagement - ns=0;i=11713 */
+
+static UA_StatusCode function_ua_namespace0_71_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.dataType = UA_NODEID_NUMERIC(ns[0], 7);
+UA_Variant_setScalar(&attr.value, NULL, &UA_TYPES[UA_TYPES_UINT32]);
+attr.displayName = UA_LOCALIZEDTEXT("", "MaxNodesPerNodeManagement");
+attr.description = UA_LOCALIZEDTEXT("", "The maximum number of operations in a single AddNodes, AddReferences, DeleteNodes or DeleteReferences request.");
+attr.writeMask = 0;
+attr.userWriteMask = 0;
+retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_VARIABLE,
+UA_NODEID_NUMERIC(ns[0], 11713),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_QUALIFIEDNAME(ns[0], "MaxNodesPerNodeManagement"),
+UA_NODEID_NUMERIC(ns[0], 68),
+(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
+retVal |= UA_Server_addReference(server, UA_NODEID_NUMERIC(ns[0], 11713), UA_NODEID_NUMERIC(ns[0], 46), UA_EXPANDEDNODEID_NUMERIC(ns[0], 11704), false);
+return retVal;
+}
+
+static UA_StatusCode function_ua_namespace0_71_finish(UA_Server *server, UA_UInt16* ns) {
+
+return UA_Server_addNode_finish(server,
+UA_NODEID_NUMERIC(ns[0], 11713)
+);
+}
+
+/* ModellingRuleType - ns=0;i=77 */
+
+static UA_StatusCode function_ua_namespace0_72_begin(UA_Server *server, UA_UInt16* ns) {
+
+UA_StatusCode retVal = UA_STATUSCODE_GOOD;
+UA_ObjectTypeAttributes attr = UA_ObjectTypeAttributes_default;
+attr.displayName = UA_LOCALIZEDTEXT("", "ModellingRuleType");
+attr.description = UA_LOCALIZEDTEXT("", "The type for an object that describes how an instance declaration is used when a type is instantiated.");
+attr.writeMask = 0;
+attr.userWriteMask = 0;
+retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_OBJECTTYPE,
+UA_NODEID_NUMERIC(ns[0], 77),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_QUALIFIEDNAME(ns[0], "ModellingRuleType"),
+UA_NODEID_NULL,
+(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_OBJECTTYPEATTRIBUTES],NULL, NULL);
+retVal |= UA_Server_addReference(server, UA_NODEID_NUMERIC(ns[0], 77), UA_NODEID_NUMERIC(ns[0], 45), UA_EXPANDEDNODEID_NUMERIC(ns[0], 58), false);
+return retVal;
+}
+
+static UA_StatusCode function_ua_namespace0_72_finish(UA_Server *server, UA_UInt16* ns) {
+
+return UA_Server_addNode_finish(server,
+UA_NODEID_NUMERIC(ns[0], 77)
+);
+}
+
+/* NamingRule - ns=0;i=111 */
+
+static UA_StatusCode function_ua_namespace0_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;
+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;
+*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");
+attr.description = UA_LOCALIZEDTEXT("", "Specified the significances of the BrowseName when a type is instantiated.");
+attr.writeMask = 0;
+attr.userWriteMask = 0;
+retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_VARIABLE,
+UA_NODEID_NUMERIC(ns[0], 111),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_QUALIFIEDNAME(ns[0], "NamingRule"),
+UA_NODEID_NUMERIC(ns[0], 68),
+(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
+UA_Int32_delete(variablenode_ns_0_i_111_variant_DataContents);
+retVal |= UA_Server_addReference(server, UA_NODEID_NUMERIC(ns[0], 111), UA_NODEID_NUMERIC(ns[0], 46), UA_EXPANDEDNODEID_NUMERIC(ns[0], 77), false);
+return retVal;
+}
+
+static UA_StatusCode function_ua_namespace0_73_finish(UA_Server *server, UA_UInt16* ns) {
+
+return UA_Server_addNode_finish(server,
+UA_NODEID_NUMERIC(ns[0], 111)
+);
+}
+
+/* Mandatory - ns=0;i=78 */
+
+static UA_StatusCode function_ua_namespace0_74_begin(UA_Server *server, UA_UInt16* ns) {
+
+UA_StatusCode retVal = UA_STATUSCODE_GOOD;
+UA_ObjectAttributes attr = UA_ObjectAttributes_default;
+attr.displayName = UA_LOCALIZEDTEXT("", "Mandatory");
+attr.description = UA_LOCALIZEDTEXT("", "Specifies that an instance with the attributes and references of the instance declaration must appear when a type is instantiated.");
+attr.writeMask = 0;
+attr.userWriteMask = 0;
+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], 2035), 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], 2160), 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], 35), UA_EXPANDEDNODEID_NUMERIC(ns[0], 2996), false);
+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], 2153), 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], 2151), 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], 2157), 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], 2155), 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], 2159), 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], 2162), false);
+return retVal;
+}
+
+static UA_StatusCode function_ua_namespace0_74_finish(UA_Server *server, UA_UInt16* ns) {
+
+return UA_Server_addNode_finish(server,
+UA_NODEID_NUMERIC(ns[0], 78)
+);
+}
+
+/* NamingRule - ns=0;i=112 */
+
+static UA_StatusCode function_ua_namespace0_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;
+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;
+*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");
+attr.description = UA_LOCALIZEDTEXT("", "Specified the significances of the BrowseName when a type is instantiated.");
+attr.writeMask = 0;
+attr.userWriteMask = 0;
+retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_VARIABLE,
+UA_NODEID_NUMERIC(ns[0], 112),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_QUALIFIEDNAME(ns[0], "NamingRule"),
+UA_NODEID_NUMERIC(ns[0], 68),
+(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
+UA_Int32_delete(variablenode_ns_0_i_112_variant_DataContents);
+retVal |= UA_Server_addReference(server, UA_NODEID_NUMERIC(ns[0], 112), UA_NODEID_NUMERIC(ns[0], 46), UA_EXPANDEDNODEID_NUMERIC(ns[0], 78), false);
+return retVal;
+}
+
+static UA_StatusCode function_ua_namespace0_75_finish(UA_Server *server, UA_UInt16* ns) {
+
+return UA_Server_addNode_finish(server,
+UA_NODEID_NUMERIC(ns[0], 112)
+);
+}
+
+/* Optional - ns=0;i=80 */
+
+static UA_StatusCode function_ua_namespace0_76_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.description = UA_LOCALIZEDTEXT("", "Specifies that an instance with the attributes and references of the instance declaration may appear when a type is instantiated.");
+attr.writeMask = 0;
+attr.userWriteMask = 0;
+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),
+(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], 35), UA_EXPANDEDNODEID_NUMERIC(ns[0], 2996), 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], 11565), 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], 11574), 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], 11570), false);
+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], 11572), 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);
+return retVal;
+}
+
+static UA_StatusCode function_ua_namespace0_76_finish(UA_Server *server, UA_UInt16* ns) {
+
+return UA_Server_addNode_finish(server,
+UA_NODEID_NUMERIC(ns[0], 80)
+);
+}
+
+/* NamingRule - ns=0;i=113 */
+
+static UA_StatusCode function_ua_namespace0_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;
+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;
+*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");
+attr.description = UA_LOCALIZEDTEXT("", "Specified the significances of the BrowseName when a type is instantiated.");
+attr.writeMask = 0;
+attr.userWriteMask = 0;
+retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_VARIABLE,
+UA_NODEID_NUMERIC(ns[0], 113),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_QUALIFIEDNAME(ns[0], "NamingRule"),
+UA_NODEID_NUMERIC(ns[0], 68),
+(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
+UA_Int32_delete(variablenode_ns_0_i_113_variant_DataContents);
+retVal |= UA_Server_addReference(server, UA_NODEID_NUMERIC(ns[0], 113), UA_NODEID_NUMERIC(ns[0], 46), UA_EXPANDEDNODEID_NUMERIC(ns[0], 80), false);
+return retVal;
+}
+
+static UA_StatusCode function_ua_namespace0_77_finish(UA_Server *server, UA_UInt16* ns) {
+
+return UA_Server_addNode_finish(server,
+UA_NODEID_NUMERIC(ns[0], 113)
+);
+}
+
+/* DataTypeEncodingType - ns=0;i=76 */
+
+static UA_StatusCode function_ua_namespace0_78_begin(UA_Server *server, UA_UInt16* ns) {
+
+UA_StatusCode retVal = UA_STATUSCODE_GOOD;
+UA_ObjectTypeAttributes attr = UA_ObjectTypeAttributes_default;
+attr.displayName = UA_LOCALIZEDTEXT("", "DataTypeEncodingType");
+attr.description = UA_LOCALIZEDTEXT("", "");
+attr.writeMask = 0;
+attr.userWriteMask = 0;
+retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_OBJECTTYPE,
+UA_NODEID_NUMERIC(ns[0], 76),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_QUALIFIEDNAME(ns[0], "DataTypeEncodingType"),
+UA_NODEID_NULL,
+(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_OBJECTTYPEATTRIBUTES],NULL, NULL);
+retVal |= UA_Server_addReference(server, UA_NODEID_NUMERIC(ns[0], 76), UA_NODEID_NUMERIC(ns[0], 45), UA_EXPANDEDNODEID_NUMERIC(ns[0], 58), false);
+return retVal;
+}
+
+static UA_StatusCode function_ua_namespace0_78_finish(UA_Server *server, UA_UInt16* ns) {
+
+return UA_Server_addNode_finish(server,
+UA_NODEID_NUMERIC(ns[0], 76)
+);
+}
+
+/* Default Binary - ns=0;i=8251 */
+
+static UA_StatusCode function_ua_namespace0_79_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.description = UA_LOCALIZEDTEXT("", "");
+attr.writeMask = 0;
+attr.userWriteMask = 0;
+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_QUALIFIEDNAME(ns[0], "Default Binary"),
+UA_NODEID_NUMERIC(ns[0], 76),
+(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);
+return retVal;
+}
+
+static UA_StatusCode function_ua_namespace0_79_finish(UA_Server *server, UA_UInt16* ns) {
+
+return UA_Server_addNode_finish(server,
+UA_NODEID_NUMERIC(ns[0], 8251)
+);
+}
+
+/* DataTypeSystemType - ns=0;i=75 */
+
+static UA_StatusCode function_ua_namespace0_80_begin(UA_Server *server, UA_UInt16* ns) {
+
+UA_StatusCode retVal = UA_STATUSCODE_GOOD;
+UA_ObjectTypeAttributes attr = UA_ObjectTypeAttributes_default;
+attr.displayName = UA_LOCALIZEDTEXT("", "DataTypeSystemType");
+attr.description = UA_LOCALIZEDTEXT("", "");
+attr.writeMask = 0;
+attr.userWriteMask = 0;
+retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_OBJECTTYPE,
+UA_NODEID_NUMERIC(ns[0], 75),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_QUALIFIEDNAME(ns[0], "DataTypeSystemType"),
+UA_NODEID_NULL,
+(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_OBJECTTYPEATTRIBUTES],NULL, NULL);
+retVal |= UA_Server_addReference(server, UA_NODEID_NUMERIC(ns[0], 75), UA_NODEID_NUMERIC(ns[0], 45), UA_EXPANDEDNODEID_NUMERIC(ns[0], 58), false);
+return retVal;
+}
+
+static UA_StatusCode function_ua_namespace0_80_finish(UA_Server *server, UA_UInt16* ns) {
+
+return UA_Server_addNode_finish(server,
+UA_NODEID_NUMERIC(ns[0], 75)
+);
+}
+
+/* OPC Binary - ns=0;i=93 */
+
+static UA_StatusCode function_ua_namespace0_81_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.description = UA_LOCALIZEDTEXT("", "A type system which uses OPC binary schema to describe the encoding of data types.");
+attr.writeMask = 0;
+attr.userWriteMask = 0;
+retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_OBJECT,
+UA_NODEID_NUMERIC(ns[0], 93),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_QUALIFIEDNAME(ns[0], "OPC Binary"),
+UA_NODEID_NUMERIC(ns[0], 75),
+(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_OBJECTATTRIBUTES],NULL, NULL);
+retVal |= UA_Server_addReference(server, UA_NODEID_NUMERIC(ns[0], 93), UA_NODEID_NUMERIC(ns[0], 35), UA_EXPANDEDNODEID_NUMERIC(ns[0], 90), false);
+return retVal;
+}
+
+static UA_StatusCode function_ua_namespace0_81_finish(UA_Server *server, UA_UInt16* ns) {
+
+return UA_Server_addNode_finish(server,
+UA_NODEID_NUMERIC(ns[0], 93)
+);
+}
+
+/* DataTypeDictionaryType - ns=0;i=72 */
+
+static UA_StatusCode function_ua_namespace0_82_begin(UA_Server *server, UA_UInt16* ns) {
+
+UA_StatusCode retVal = UA_STATUSCODE_GOOD;
+UA_VariableTypeAttributes attr = UA_VariableTypeAttributes_default;
+attr.valueRank = (UA_Int32)-2;
+attr.dataType = UA_NODEID_NUMERIC(ns[0], 24);
+attr.displayName = UA_LOCALIZEDTEXT("", "DataTypeDictionaryType");
+attr.description = UA_LOCALIZEDTEXT("", "The type for variable that represents the collection of data type decriptions.");
+attr.writeMask = 0;
+attr.userWriteMask = 0;
+retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_VARIABLETYPE,
+UA_NODEID_NUMERIC(ns[0], 72),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_QUALIFIEDNAME(ns[0], "DataTypeDictionaryType"),
+UA_NODEID_NUMERIC(ns[0], 63),
+(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_VARIABLETYPEATTRIBUTES],NULL, NULL);
+retVal |= UA_Server_addReference(server, UA_NODEID_NUMERIC(ns[0], 72), UA_NODEID_NUMERIC(ns[0], 45), UA_EXPANDEDNODEID_NUMERIC(ns[0], 63), false);
+return retVal;
+}
+
+static UA_StatusCode function_ua_namespace0_82_finish(UA_Server *server, UA_UInt16* ns) {
+
+return UA_Server_addNode_finish(server,
+UA_NODEID_NUMERIC(ns[0], 72)
+);
+}
+
+/* NamespaceUri - ns=0;i=107 */
+
+static UA_StatusCode function_ua_namespace0_83_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.dataType = UA_NODEID_NUMERIC(ns[0], 12);
+UA_Variant_setScalar(&attr.value, NULL, &UA_TYPES[UA_TYPES_STRING]);
+attr.displayName = UA_LOCALIZEDTEXT("", "NamespaceUri");
+attr.description = UA_LOCALIZEDTEXT("", "A URI that uniquely identifies the dictionary.");
+attr.writeMask = 0;
+attr.userWriteMask = 0;
+retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_VARIABLE,
+UA_NODEID_NUMERIC(ns[0], 107),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_QUALIFIEDNAME(ns[0], "NamespaceUri"),
+UA_NODEID_NUMERIC(ns[0], 68),
+(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], 107), UA_NODEID_NUMERIC(ns[0], 46), UA_EXPANDEDNODEID_NUMERIC(ns[0], 72), false);
+return retVal;
+}
+
+static UA_StatusCode function_ua_namespace0_83_finish(UA_Server *server, UA_UInt16* ns) {
+
+return UA_Server_addNode_finish(server,
+UA_NODEID_NUMERIC(ns[0], 107)
+);
+}
+
+/* DataTypeVersion - ns=0;i=106 */
+
+static UA_StatusCode function_ua_namespace0_84_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.dataType = UA_NODEID_NUMERIC(ns[0], 12);
+UA_Variant_setScalar(&attr.value, NULL, &UA_TYPES[UA_TYPES_STRING]);
+attr.displayName = UA_LOCALIZEDTEXT("", "DataTypeVersion");
+attr.description = UA_LOCALIZEDTEXT("", "The version number for the data type dictionary.");
+attr.writeMask = 0;
+attr.userWriteMask = 0;
+retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_VARIABLE,
+UA_NODEID_NUMERIC(ns[0], 106),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_QUALIFIEDNAME(ns[0], "DataTypeVersion"),
+UA_NODEID_NUMERIC(ns[0], 68),
+(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], 106), UA_NODEID_NUMERIC(ns[0], 46), UA_EXPANDEDNODEID_NUMERIC(ns[0], 72), false);
+return retVal;
+}
+
+static UA_StatusCode function_ua_namespace0_84_finish(UA_Server *server, UA_UInt16* ns) {
+
+return UA_Server_addNode_finish(server,
+UA_NODEID_NUMERIC(ns[0], 106)
+);
+}
+
+/* Opc.Ua - ns=0;i=7617 */
+
+static UA_StatusCode function_ua_namespace0_85_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.dataType = UA_NODEID_NUMERIC(ns[0], 15);
+UA_ByteString *variablenode_ns_0_i_7617_variant_DataContents = UA_ByteString_new();
+if (!variablenode_ns_0_i_7617_variant_DataContents) return UA_STATUSCODE_BADOUTOFMEMORY;
+*variablenode_ns_0_i_7617_variant_DataContents = UA_BYTESTRING_NULL;
+UA_Variant_setScalar(&attr.value, variablenode_ns_0_i_7617_variant_DataContents, &UA_TYPES[UA_TYPES_BYTESTRING]);
+attr.displayName = UA_LOCALIZEDTEXT("", "Opc.Ua");
+attr.description = UA_LOCALIZEDTEXT("", "");
+attr.writeMask = 0;
+attr.userWriteMask = 0;
+retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_VARIABLE,
+UA_NODEID_NUMERIC(ns[0], 7617),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_QUALIFIEDNAME(ns[0], "Opc.Ua"),
+UA_NODEID_NUMERIC(ns[0], 72),
+(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
+UA_ByteString_delete(variablenode_ns_0_i_7617_variant_DataContents);
+retVal |= UA_Server_addReference(server, UA_NODEID_NUMERIC(ns[0], 7617), UA_NODEID_NUMERIC(ns[0], 47), UA_EXPANDEDNODEID_NUMERIC(ns[0], 93), false);
+return retVal;
+}
+
+static UA_StatusCode function_ua_namespace0_85_finish(UA_Server *server, UA_UInt16* ns) {
+
+return UA_Server_addNode_finish(server,
+UA_NODEID_NUMERIC(ns[0], 7617)
+);
+}
+
+/* ServerStatusDataType - ns=0;i=862 */
+
+static UA_StatusCode function_ua_namespace0_86_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.description = UA_LOCALIZEDTEXT("", "");
+attr.writeMask = 0;
+attr.userWriteMask = 0;
+retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_DATATYPE,
+UA_NODEID_NUMERIC(ns[0], 862),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_QUALIFIEDNAME(ns[0], "ServerStatusDataType"),
+UA_NODEID_NULL,
+(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_DATATYPEATTRIBUTES],NULL, NULL);
+retVal |= UA_Server_addReference(server, UA_NODEID_NUMERIC(ns[0], 862), UA_NODEID_NUMERIC(ns[0], 45), UA_EXPANDEDNODEID_NUMERIC(ns[0], 22), false);
+return retVal;
+}
+
+static UA_StatusCode function_ua_namespace0_86_finish(UA_Server *server, UA_UInt16* ns) {
+
+return UA_Server_addNode_finish(server,
+UA_NODEID_NUMERIC(ns[0], 862)
+);
+}
+
+/* DataTypeDescriptionType - ns=0;i=69 */
+
+static UA_StatusCode function_ua_namespace0_87_begin(UA_Server *server, UA_UInt16* ns) {
+
+UA_StatusCode retVal = UA_STATUSCODE_GOOD;
+UA_VariableTypeAttributes attr = UA_VariableTypeAttributes_default;
+attr.valueRank = (UA_Int32)-2;
+attr.dataType = UA_NODEID_NUMERIC(ns[0], 24);
+attr.displayName = UA_LOCALIZEDTEXT("", "DataTypeDescriptionType");
+attr.description = UA_LOCALIZEDTEXT("", "The type for variable that represents the description of a data type encoding.");
+attr.writeMask = 0;
+attr.userWriteMask = 0;
+retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_VARIABLETYPE,
+UA_NODEID_NUMERIC(ns[0], 69),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_QUALIFIEDNAME(ns[0], "DataTypeDescriptionType"),
+UA_NODEID_NUMERIC(ns[0], 63),
+(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_VARIABLETYPEATTRIBUTES],NULL, NULL);
+retVal |= UA_Server_addReference(server, UA_NODEID_NUMERIC(ns[0], 69), UA_NODEID_NUMERIC(ns[0], 45), UA_EXPANDEDNODEID_NUMERIC(ns[0], 63), false);
+return retVal;
+}
+
+static UA_StatusCode function_ua_namespace0_87_finish(UA_Server *server, UA_UInt16* ns) {
+
+return UA_Server_addNode_finish(server,
+UA_NODEID_NUMERIC(ns[0], 69)
+);
+}
+
+/* DictionaryFragment - ns=0;i=105 */
+
+static UA_StatusCode function_ua_namespace0_88_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.dataType = UA_NODEID_NUMERIC(ns[0], 15);
+UA_Variant_setScalar(&attr.value, NULL, &UA_TYPES[UA_TYPES_BYTESTRING]);
+attr.displayName = UA_LOCALIZEDTEXT("", "DictionaryFragment");
+attr.description = UA_LOCALIZEDTEXT("", "A fragment of a data type dictionary that defines the data type.");
+attr.writeMask = 0;
+attr.userWriteMask = 0;
+retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_VARIABLE,
+UA_NODEID_NUMERIC(ns[0], 105),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_QUALIFIEDNAME(ns[0], "DictionaryFragment"),
+UA_NODEID_NUMERIC(ns[0], 68),
+(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);
+retVal |= UA_Server_addReference(server, UA_NODEID_NUMERIC(ns[0], 105), UA_NODEID_NUMERIC(ns[0], 46), UA_EXPANDEDNODEID_NUMERIC(ns[0], 69), false);
+return retVal;
+}
+
+static UA_StatusCode function_ua_namespace0_88_finish(UA_Server *server, UA_UInt16* ns) {
+
+return UA_Server_addNode_finish(server,
+UA_NODEID_NUMERIC(ns[0], 105)
+);
+}
+
+/* DataTypeVersion - ns=0;i=104 */
+
+static UA_StatusCode function_ua_namespace0_89_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.dataType = UA_NODEID_NUMERIC(ns[0], 12);
+UA_Variant_setScalar(&attr.value, NULL, &UA_TYPES[UA_TYPES_STRING]);
+attr.displayName = UA_LOCALIZEDTEXT("", "DataTypeVersion");
+attr.description = UA_LOCALIZEDTEXT("", "The version number for the data type description.");
+attr.writeMask = 0;
+attr.userWriteMask = 0;
+retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_VARIABLE,
+UA_NODEID_NUMERIC(ns[0], 104),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_QUALIFIEDNAME(ns[0], "DataTypeVersion"),
+UA_NODEID_NUMERIC(ns[0], 68),
+(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], 104), UA_NODEID_NUMERIC(ns[0], 46), UA_EXPANDEDNODEID_NUMERIC(ns[0], 69), false);
+return retVal;
+}
+
+static UA_StatusCode function_ua_namespace0_89_finish(UA_Server *server, UA_UInt16* ns) {
+
+return UA_Server_addNode_finish(server,
+UA_NODEID_NUMERIC(ns[0], 104)
+);
+}
+
+/* Argument - ns=0;i=7650 */
+
+static UA_StatusCode function_ua_namespace0_90_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.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;
+*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.description = UA_LOCALIZEDTEXT("", "");
+attr.writeMask = 0;
+attr.userWriteMask = 0;
+retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_VARIABLE,
+UA_NODEID_NUMERIC(ns[0], 7650),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_QUALIFIEDNAME(ns[0], "Argument"),
+UA_NODEID_NUMERIC(ns[0], 69),
+(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], 47), UA_EXPANDEDNODEID_NUMERIC(ns[0], 7617), false);
+return retVal;
+}
+
+static UA_StatusCode function_ua_namespace0_90_finish(UA_Server *server, UA_UInt16* ns) {
+
+return UA_Server_addNode_finish(server,
+UA_NODEID_NUMERIC(ns[0], 7650)
+);
+}
+
+/* EnumValueType - ns=0;i=7656 */
+
+static UA_StatusCode function_ua_namespace0_91_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.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;
+*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.description = UA_LOCALIZEDTEXT("", "");
+attr.writeMask = 0;
+attr.userWriteMask = 0;
+retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_VARIABLE,
+UA_NODEID_NUMERIC(ns[0], 7656),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_QUALIFIEDNAME(ns[0], "EnumValueType"),
+UA_NODEID_NUMERIC(ns[0], 69),
+(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], 47), UA_EXPANDEDNODEID_NUMERIC(ns[0], 7617), false);
+retVal |= UA_Server_addReference(server, UA_NODEID_NUMERIC(ns[0], 7656), UA_NODEID_NUMERIC(ns[0], 39), UA_EXPANDEDNODEID_NUMERIC(ns[0], 8251), false);
+return retVal;
+}
+
+static UA_StatusCode function_ua_namespace0_91_finish(UA_Server *server, UA_UInt16* ns) {
+
+return UA_Server_addNode_finish(server,
+UA_NODEID_NUMERIC(ns[0], 7656)
+);
+}
+
+/* ServerDiagnosticsSummaryDataType - ns=0;i=859 */
+
+static UA_StatusCode function_ua_namespace0_92_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.description = UA_LOCALIZEDTEXT("", "");
+attr.writeMask = 0;
+attr.userWriteMask = 0;
+retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_DATATYPE,
+UA_NODEID_NUMERIC(ns[0], 859),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_QUALIFIEDNAME(ns[0], "ServerDiagnosticsSummaryDataType"),
+UA_NODEID_NULL,
+(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_DATATYPEATTRIBUTES],NULL, NULL);
+retVal |= UA_Server_addReference(server, UA_NODEID_NUMERIC(ns[0], 859), UA_NODEID_NUMERIC(ns[0], 45), UA_EXPANDEDNODEID_NUMERIC(ns[0], 22), false);
+return retVal;
+}
+
+static UA_StatusCode function_ua_namespace0_92_finish(UA_Server *server, UA_UInt16* ns) {
+
+return UA_Server_addNode_finish(server,
+UA_NODEID_NUMERIC(ns[0], 859)
+);
+}
+
+/* SignedSoftwareCertificate - ns=0;i=344 */
+
+static UA_StatusCode function_ua_namespace0_93_begin(UA_Server *server, UA_UInt16* ns) {
+
+UA_StatusCode retVal = UA_STATUSCODE_GOOD;
+UA_DataTypeAttributes attr = UA_DataTypeAttributes_default;
+attr.displayName = UA_LOCALIZEDTEXT("", "SignedSoftwareCertificate");
+attr.description = UA_LOCALIZEDTEXT("", "A software certificate with a digital signature.");
+attr.writeMask = 0;
+attr.userWriteMask = 0;
+retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_DATATYPE,
+UA_NODEID_NUMERIC(ns[0], 344),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_QUALIFIEDNAME(ns[0], "SignedSoftwareCertificate"),
+UA_NODEID_NULL,
+(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_DATATYPEATTRIBUTES],NULL, NULL);
+retVal |= UA_Server_addReference(server, UA_NODEID_NUMERIC(ns[0], 344), UA_NODEID_NUMERIC(ns[0], 45), UA_EXPANDEDNODEID_NUMERIC(ns[0], 22), false);
+return retVal;
+}
+
+static UA_StatusCode function_ua_namespace0_93_finish(UA_Server *server, UA_UInt16* ns) {
+
+return UA_Server_addNode_finish(server,
+UA_NODEID_NUMERIC(ns[0], 344)
+);
+}
+
+/* SoftwareCertificates - ns=0;i=3704 */
+
+static UA_StatusCode function_ua_namespace0_94_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;
+attr.arrayDimensions = (UA_UInt32 *)UA_Array_new(1, &UA_TYPES[UA_TYPES_UINT32]);
+if (!attr.arrayDimensions) return UA_STATUSCODE_BADOUTOFMEMORY;
+attr.arrayDimensions[0] = 0;
+attr.dataType = UA_NODEID_NUMERIC(ns[0], 344);
+UA_Variant_setArray(&attr.value, NULL, (UA_Int32) 0, &UA_TYPES[UA_TYPES_SIGNEDSOFTWARECERTIFICATE]);
+attr.displayName = UA_LOCALIZEDTEXT("", "SoftwareCertificates");
+attr.description = UA_LOCALIZEDTEXT("", "The software certificates owned by the server.");
+attr.writeMask = 0;
+attr.userWriteMask = 0;
+retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_VARIABLE,
+UA_NODEID_NUMERIC(ns[0], 3704),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_QUALIFIEDNAME(ns[0], "SoftwareCertificates"),
+UA_NODEID_NUMERIC(ns[0], 68),
+(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
+UA_Array_delete(attr.arrayDimensions, 1, &UA_TYPES[UA_TYPES_UINT32]);
+retVal |= UA_Server_addReference(server, UA_NODEID_NUMERIC(ns[0], 3704), UA_NODEID_NUMERIC(ns[0], 46), UA_EXPANDEDNODEID_NUMERIC(ns[0], 2268), false);
+return retVal;
+}
+
+static UA_StatusCode function_ua_namespace0_94_finish(UA_Server *server, UA_UInt16* ns) {
+
+return UA_Server_addNode_finish(server,
+UA_NODEID_NUMERIC(ns[0], 3704)
+);
+}
+
+/* VendorServerInfoType - ns=0;i=2033 */
+
+static UA_StatusCode function_ua_namespace0_95_begin(UA_Server *server, UA_UInt16* ns) {
+
+UA_StatusCode retVal = UA_STATUSCODE_GOOD;
+UA_ObjectTypeAttributes attr = UA_ObjectTypeAttributes_default;
+attr.displayName = UA_LOCALIZEDTEXT("", "VendorServerInfoType");
+attr.description = UA_LOCALIZEDTEXT("", "A base type for vendor specific server information.");
+attr.writeMask = 0;
+attr.userWriteMask = 0;
+retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_OBJECTTYPE,
+UA_NODEID_NUMERIC(ns[0], 2033),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_QUALIFIEDNAME(ns[0], "VendorServerInfoType"),
+UA_NODEID_NULL,
+(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_OBJECTTYPEATTRIBUTES],NULL, NULL);
+retVal |= UA_Server_addReference(server, UA_NODEID_NUMERIC(ns[0], 2033), UA_NODEID_NUMERIC(ns[0], 45), UA_EXPANDEDNODEID_NUMERIC(ns[0], 58), false);
+return retVal;
+}
+
+static UA_StatusCode function_ua_namespace0_95_finish(UA_Server *server, UA_UInt16* ns) {
+
+return UA_Server_addNode_finish(server,
+UA_NODEID_NUMERIC(ns[0], 2033)
+);
+}
+
+/* VendorServerInfo - ns=0;i=2295 */
+
+static UA_StatusCode function_ua_namespace0_96_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.description = UA_LOCALIZEDTEXT("", "Server information provided by the vendor.");
+attr.writeMask = 0;
+attr.userWriteMask = 0;
+retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_OBJECT,
+UA_NODEID_NUMERIC(ns[0], 2295),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_QUALIFIEDNAME(ns[0], "VendorServerInfo"),
+UA_NODEID_NUMERIC(ns[0], 2033),
+(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_OBJECTATTRIBUTES],NULL, NULL);
+retVal |= UA_Server_addReference(server, UA_NODEID_NUMERIC(ns[0], 2295), UA_NODEID_NUMERIC(ns[0], 47), UA_EXPANDEDNODEID_NUMERIC(ns[0], 2253), false);
+return retVal;
+}
+
+static UA_StatusCode function_ua_namespace0_96_finish(UA_Server *server, UA_UInt16* ns) {
+
+return UA_Server_addNode_finish(server,
+UA_NODEID_NUMERIC(ns[0], 2295)
+);
+}
+
+/* VendorServerInfo - ns=0;i=2011 */
+
+static UA_StatusCode function_ua_namespace0_97_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.description = UA_LOCALIZEDTEXT("", "Server information provided by the vendor.");
+attr.writeMask = 0;
+attr.userWriteMask = 0;
+retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_OBJECT,
+UA_NODEID_NUMERIC(ns[0], 2011),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_QUALIFIEDNAME(ns[0], "VendorServerInfo"),
+UA_NODEID_NUMERIC(ns[0], 2033),
+(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_OBJECTATTRIBUTES],NULL, NULL);
+retVal |= UA_Server_addReference(server, UA_NODEID_NUMERIC(ns[0], 2011), UA_NODEID_NUMERIC(ns[0], 37), UA_EXPANDEDNODEID_NUMERIC(ns[0], 78), true);
+retVal |= UA_Server_addReference(server, UA_NODEID_NUMERIC(ns[0], 2011), UA_NODEID_NUMERIC(ns[0], 47), UA_EXPANDEDNODEID_NUMERIC(ns[0], 2004), false);
+return retVal;
+}
+
+static UA_StatusCode function_ua_namespace0_97_finish(UA_Server *server, UA_UInt16* ns) {
+
+return UA_Server_addNode_finish(server,
+UA_NODEID_NUMERIC(ns[0], 2011)
+);
+}
+
+/* ServerStatusType - ns=0;i=2138 */
+
+static UA_StatusCode function_ua_namespace0_98_begin(UA_Server *server, UA_UInt16* ns) {
+
+UA_StatusCode retVal = UA_STATUSCODE_GOOD;
+UA_VariableTypeAttributes attr = UA_VariableTypeAttributes_default;
+attr.valueRank = (UA_Int32)-2;
+attr.dataType = UA_NODEID_NUMERIC(ns[0], 24);
+attr.displayName = UA_LOCALIZEDTEXT("", "ServerStatusType");
+attr.description = UA_LOCALIZEDTEXT("", "");
+attr.writeMask = 0;
+attr.userWriteMask = 0;
+retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_VARIABLETYPE,
+UA_NODEID_NUMERIC(ns[0], 2138),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_QUALIFIEDNAME(ns[0], "ServerStatusType"),
+UA_NODEID_NUMERIC(ns[0], 63),
+(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_VARIABLETYPEATTRIBUTES],NULL, NULL);
+retVal |= UA_Server_addReference(server, UA_NODEID_NUMERIC(ns[0], 2138), UA_NODEID_NUMERIC(ns[0], 45), UA_EXPANDEDNODEID_NUMERIC(ns[0], 63), false);
+return retVal;
+}
+
+static UA_StatusCode function_ua_namespace0_98_finish(UA_Server *server, UA_UInt16* ns) {
+
+return UA_Server_addNode_finish(server,
+UA_NODEID_NUMERIC(ns[0], 2138)
+);
+}
+
+/* ServerStatus - ns=0;i=2256 */
+
+static UA_StatusCode function_ua_namespace0_99_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.dataType = UA_NODEID_NUMERIC(ns[0], 862);
+UA_Variant_setScalar(&attr.value, NULL, &UA_TYPES[UA_TYPES_SERVERSTATUSDATATYPE]);
+attr.displayName = UA_LOCALIZEDTEXT("", "ServerStatus");
+attr.description = UA_LOCALIZEDTEXT("", "The current status of the server.");
+attr.writeMask = 0;
+attr.userWriteMask = 0;
+retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_VARIABLE,
+UA_NODEID_NUMERIC(ns[0], 2256),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_QUALIFIEDNAME(ns[0], "ServerStatus"),
+UA_NODEID_NUMERIC(ns[0], 2138),
+(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
+retVal |= UA_Server_addReference(server, UA_NODEID_NUMERIC(ns[0], 2256), UA_NODEID_NUMERIC(ns[0], 47), UA_EXPANDEDNODEID_NUMERIC(ns[0], 2253), false);
+return retVal;
+}
+
+static UA_StatusCode function_ua_namespace0_99_finish(UA_Server *server, UA_UInt16* ns) {
+
+return UA_Server_addNode_finish(server,
+UA_NODEID_NUMERIC(ns[0], 2256)
+);
+}
+
+/* State - ns=0;i=2259 */
+
+static UA_StatusCode function_ua_namespace0_100_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.dataType = UA_NODEID_NUMERIC(ns[0], 852);
+UA_Variant_setScalar(&attr.value, NULL, &UA_TYPES[UA_TYPES_SERVERSTATE]);
+attr.displayName = UA_LOCALIZEDTEXT("", "State");
+attr.description = UA_LOCALIZEDTEXT("", "");
+attr.writeMask = 0;
+attr.userWriteMask = 0;
+retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_VARIABLE,
+UA_NODEID_NUMERIC(ns[0], 2259),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_QUALIFIEDNAME(ns[0], "State"),
+UA_NODEID_NUMERIC(ns[0], 63),
+(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
+retVal |= UA_Server_addReference(server, UA_NODEID_NUMERIC(ns[0], 2259), UA_NODEID_NUMERIC(ns[0], 47), UA_EXPANDEDNODEID_NUMERIC(ns[0], 2256), false);
+return retVal;
+}
+
+static UA_StatusCode function_ua_namespace0_100_finish(UA_Server *server, UA_UInt16* ns) {
+
+return UA_Server_addNode_finish(server,
+UA_NODEID_NUMERIC(ns[0], 2259)
+);
+}
+
+/* CurrentTime - ns=0;i=2258 */
+
+static UA_StatusCode function_ua_namespace0_101_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.dataType = UA_NODEID_NUMERIC(ns[0], 294);
+UA_Variant_setScalar(&attr.value, NULL, &UA_TYPES[UA_TYPES_DATETIME]);
+attr.displayName = UA_LOCALIZEDTEXT("", "CurrentTime");
+attr.description = UA_LOCALIZEDTEXT("", "");
+attr.writeMask = 0;
+attr.userWriteMask = 0;
+retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_VARIABLE,
+UA_NODEID_NUMERIC(ns[0], 2258),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_QUALIFIEDNAME(ns[0], "CurrentTime"),
+UA_NODEID_NUMERIC(ns[0], 63),
+(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
+retVal |= UA_Server_addReference(server, UA_NODEID_NUMERIC(ns[0], 2258), UA_NODEID_NUMERIC(ns[0], 47), UA_EXPANDEDNODEID_NUMERIC(ns[0], 2256), false);
+return retVal;
+}
+
+static UA_StatusCode function_ua_namespace0_101_finish(UA_Server *server, UA_UInt16* ns) {
+
+return UA_Server_addNode_finish(server,
+UA_NODEID_NUMERIC(ns[0], 2258)
+);
+}
+
+/* StartTime - ns=0;i=2257 */
+
+static UA_StatusCode function_ua_namespace0_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;
+attr.valueRank = -1;
+attr.dataType = UA_NODEID_NUMERIC(ns[0], 294);
+UA_Variant_setScalar(&attr.value, NULL, &UA_TYPES[UA_TYPES_DATETIME]);
+attr.displayName = UA_LOCALIZEDTEXT("", "StartTime");
+attr.description = UA_LOCALIZEDTEXT("", "");
+attr.writeMask = 0;
+attr.userWriteMask = 0;
+retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_VARIABLE,
+UA_NODEID_NUMERIC(ns[0], 2257),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_QUALIFIEDNAME(ns[0], "StartTime"),
+UA_NODEID_NUMERIC(ns[0], 63),
+(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
+retVal |= UA_Server_addReference(server, UA_NODEID_NUMERIC(ns[0], 2257), UA_NODEID_NUMERIC(ns[0], 47), UA_EXPANDEDNODEID_NUMERIC(ns[0], 2256), false);
+return retVal;
+}
+
+static UA_StatusCode function_ua_namespace0_102_finish(UA_Server *server, UA_UInt16* ns) {
+
+return UA_Server_addNode_finish(server,
+UA_NODEID_NUMERIC(ns[0], 2257)
+);
+}
+
+/* BuildInfo - ns=0;i=2260 */
+
+static UA_StatusCode function_ua_namespace0_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.userAccessLevel = 1;
+attr.accessLevel = 1;
+attr.valueRank = -1;
+attr.dataType = UA_NODEID_NUMERIC(ns[0], 338);
+UA_Variant_setScalar(&attr.value, NULL, &UA_TYPES[UA_TYPES_BUILDINFO]);
+attr.displayName = UA_LOCALIZEDTEXT("", "BuildInfo");
+attr.description = UA_LOCALIZEDTEXT("", "");
+attr.writeMask = 0;
+attr.userWriteMask = 0;
+retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_VARIABLE,
+UA_NODEID_NUMERIC(ns[0], 2260),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_QUALIFIEDNAME(ns[0], "BuildInfo"),
+UA_NODEID_NUMERIC(ns[0], 3051),
+(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
+retVal |= UA_Server_addReference(server, UA_NODEID_NUMERIC(ns[0], 2260), UA_NODEID_NUMERIC(ns[0], 47), UA_EXPANDEDNODEID_NUMERIC(ns[0], 2256), false);
+return retVal;
+}
+
+static UA_StatusCode function_ua_namespace0_103_finish(UA_Server *server, UA_UInt16* ns) {
+
+return UA_Server_addNode_finish(server,
+UA_NODEID_NUMERIC(ns[0], 2260)
+);
+}
+
+/* BuildDate - ns=0;i=2266 */
+
+static UA_StatusCode function_ua_namespace0_104_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.dataType = UA_NODEID_NUMERIC(ns[0], 294);
+UA_Variant_setScalar(&attr.value, NULL, &UA_TYPES[UA_TYPES_DATETIME]);
+attr.displayName = UA_LOCALIZEDTEXT("", "BuildDate");
+attr.description = UA_LOCALIZEDTEXT("", "");
+attr.writeMask = 0;
+attr.userWriteMask = 0;
+retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_VARIABLE,
+UA_NODEID_NUMERIC(ns[0], 2266),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_QUALIFIEDNAME(ns[0], "BuildDate"),
+UA_NODEID_NUMERIC(ns[0], 63),
+(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
+retVal |= UA_Server_addReference(server, UA_NODEID_NUMERIC(ns[0], 2266), UA_NODEID_NUMERIC(ns[0], 47), UA_EXPANDEDNODEID_NUMERIC(ns[0], 2260), false);
+return retVal;
+}
+
+static UA_StatusCode function_ua_namespace0_104_finish(UA_Server *server, UA_UInt16* ns) {
+
+return UA_Server_addNode_finish(server,
+UA_NODEID_NUMERIC(ns[0], 2266)
+);
+}
+
+/* BuildNumber - ns=0;i=2265 */
+
+static UA_StatusCode function_ua_namespace0_105_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.dataType = UA_NODEID_NUMERIC(ns[0], 12);
+UA_Variant_setScalar(&attr.value, NULL, &UA_TYPES[UA_TYPES_STRING]);
+attr.displayName = UA_LOCALIZEDTEXT("", "BuildNumber");
+attr.description = UA_LOCALIZEDTEXT("", "");
+attr.writeMask = 0;
+attr.userWriteMask = 0;
+retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_VARIABLE,
+UA_NODEID_NUMERIC(ns[0], 2265),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_QUALIFIEDNAME(ns[0], "BuildNumber"),
+UA_NODEID_NUMERIC(ns[0], 63),
+(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
+retVal |= UA_Server_addReference(server, UA_NODEID_NUMERIC(ns[0], 2265), UA_NODEID_NUMERIC(ns[0], 47), UA_EXPANDEDNODEID_NUMERIC(ns[0], 2260), false);
+return retVal;
+}
+
+static UA_StatusCode function_ua_namespace0_105_finish(UA_Server *server, UA_UInt16* ns) {
+
+return UA_Server_addNode_finish(server,
+UA_NODEID_NUMERIC(ns[0], 2265)
+);
+}
+
+/* SoftwareVersion - ns=0;i=2264 */
+
+static UA_StatusCode function_ua_namespace0_106_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.dataType = UA_NODEID_NUMERIC(ns[0], 12);
+UA_Variant_setScalar(&attr.value, NULL, &UA_TYPES[UA_TYPES_STRING]);
+attr.displayName = UA_LOCALIZEDTEXT("", "SoftwareVersion");
+attr.description = UA_LOCALIZEDTEXT("", "");
+attr.writeMask = 0;
+attr.userWriteMask = 0;
+retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_VARIABLE,
+UA_NODEID_NUMERIC(ns[0], 2264),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_QUALIFIEDNAME(ns[0], "SoftwareVersion"),
+UA_NODEID_NUMERIC(ns[0], 63),
+(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
+retVal |= UA_Server_addReference(server, UA_NODEID_NUMERIC(ns[0], 2264), UA_NODEID_NUMERIC(ns[0], 47), UA_EXPANDEDNODEID_NUMERIC(ns[0], 2260), false);
+return retVal;
+}
+
+static UA_StatusCode function_ua_namespace0_106_finish(UA_Server *server, UA_UInt16* ns) {
+
+return UA_Server_addNode_finish(server,
+UA_NODEID_NUMERIC(ns[0], 2264)
+);
+}
+
+/* ManufacturerName - ns=0;i=2263 */
+
+static UA_StatusCode function_ua_namespace0_107_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.dataType = UA_NODEID_NUMERIC(ns[0], 12);
+UA_Variant_setScalar(&attr.value, NULL, &UA_TYPES[UA_TYPES_STRING]);
+attr.displayName = UA_LOCALIZEDTEXT("", "ManufacturerName");
+attr.description = UA_LOCALIZEDTEXT("", "");
+attr.writeMask = 0;
+attr.userWriteMask = 0;
+retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_VARIABLE,
+UA_NODEID_NUMERIC(ns[0], 2263),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_QUALIFIEDNAME(ns[0], "ManufacturerName"),
+UA_NODEID_NUMERIC(ns[0], 63),
+(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
+retVal |= UA_Server_addReference(server, UA_NODEID_NUMERIC(ns[0], 2263), UA_NODEID_NUMERIC(ns[0], 47), UA_EXPANDEDNODEID_NUMERIC(ns[0], 2260), false);
+return retVal;
+}
+
+static UA_StatusCode function_ua_namespace0_107_finish(UA_Server *server, UA_UInt16* ns) {
+
+return UA_Server_addNode_finish(server,
+UA_NODEID_NUMERIC(ns[0], 2263)
+);
+}
+
+/* ProductUri - ns=0;i=2262 */
+
+static UA_StatusCode function_ua_namespace0_108_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.dataType = UA_NODEID_NUMERIC(ns[0], 12);
+UA_Variant_setScalar(&attr.value, NULL, &UA_TYPES[UA_TYPES_STRING]);
+attr.displayName = UA_LOCALIZEDTEXT("", "ProductUri");
+attr.description = UA_LOCALIZEDTEXT("", "");
+attr.writeMask = 0;
+attr.userWriteMask = 0;
+retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_VARIABLE,
+UA_NODEID_NUMERIC(ns[0], 2262),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_QUALIFIEDNAME(ns[0], "ProductUri"),
+UA_NODEID_NUMERIC(ns[0], 63),
+(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
+retVal |= UA_Server_addReference(server, UA_NODEID_NUMERIC(ns[0], 2262), UA_NODEID_NUMERIC(ns[0], 47), UA_EXPANDEDNODEID_NUMERIC(ns[0], 2260), false);
+return retVal;
+}
+
+static UA_StatusCode function_ua_namespace0_108_finish(UA_Server *server, UA_UInt16* ns) {
+
+return UA_Server_addNode_finish(server,
+UA_NODEID_NUMERIC(ns[0], 2262)
+);
+}
+
+/* ProductName - ns=0;i=2261 */
+
+static UA_StatusCode function_ua_namespace0_109_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.dataType = UA_NODEID_NUMERIC(ns[0], 12);
+UA_Variant_setScalar(&attr.value, NULL, &UA_TYPES[UA_TYPES_STRING]);
+attr.displayName = UA_LOCALIZEDTEXT("", "ProductName");
+attr.description = UA_LOCALIZEDTEXT("", "");
+attr.writeMask = 0;
+attr.userWriteMask = 0;
+retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_VARIABLE,
+UA_NODEID_NUMERIC(ns[0], 2261),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_QUALIFIEDNAME(ns[0], "ProductName"),
+UA_NODEID_NUMERIC(ns[0], 63),
+(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
+retVal |= UA_Server_addReference(server, UA_NODEID_NUMERIC(ns[0], 2261), UA_NODEID_NUMERIC(ns[0], 47), UA_EXPANDEDNODEID_NUMERIC(ns[0], 2260), false);
+return retVal;
+}
+
+static UA_StatusCode function_ua_namespace0_109_finish(UA_Server *server, UA_UInt16* ns) {
+
+return UA_Server_addNode_finish(server,
+UA_NODEID_NUMERIC(ns[0], 2261)
+);
+}
+
+/* SecondsTillShutdown - ns=0;i=2992 */
+
+static UA_StatusCode function_ua_namespace0_110_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.dataType = UA_NODEID_NUMERIC(ns[0], 7);
+UA_Variant_setScalar(&attr.value, NULL, &UA_TYPES[UA_TYPES_UINT32]);
+attr.displayName = UA_LOCALIZEDTEXT("", "SecondsTillShutdown");
+attr.description = UA_LOCALIZEDTEXT("", "");
+attr.writeMask = 0;
+attr.userWriteMask = 0;
+retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_VARIABLE,
+UA_NODEID_NUMERIC(ns[0], 2992),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_QUALIFIEDNAME(ns[0], "SecondsTillShutdown"),
+UA_NODEID_NUMERIC(ns[0], 63),
+(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
+retVal |= UA_Server_addReference(server, UA_NODEID_NUMERIC(ns[0], 2992), UA_NODEID_NUMERIC(ns[0], 47), UA_EXPANDEDNODEID_NUMERIC(ns[0], 2256), false);
+return retVal;
+}
+
+static UA_StatusCode function_ua_namespace0_110_finish(UA_Server *server, UA_UInt16* ns) {
+
+return UA_Server_addNode_finish(server,
+UA_NODEID_NUMERIC(ns[0], 2992)
+);
+}
+
+/* ShutdownReason - ns=0;i=2993 */
+
+static UA_StatusCode function_ua_namespace0_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;
+attr.valueRank = -1;
+attr.dataType = UA_NODEID_NUMERIC(ns[0], 21);
+UA_Variant_setScalar(&attr.value, NULL, &UA_TYPES[UA_TYPES_LOCALIZEDTEXT]);
+attr.displayName = UA_LOCALIZEDTEXT("", "ShutdownReason");
+attr.description = UA_LOCALIZEDTEXT("", "");
+attr.writeMask = 0;
+attr.userWriteMask = 0;
+retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_VARIABLE,
+UA_NODEID_NUMERIC(ns[0], 2993),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_QUALIFIEDNAME(ns[0], "ShutdownReason"),
+UA_NODEID_NUMERIC(ns[0], 63),
+(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
+retVal |= UA_Server_addReference(server, UA_NODEID_NUMERIC(ns[0], 2993), UA_NODEID_NUMERIC(ns[0], 47), UA_EXPANDEDNODEID_NUMERIC(ns[0], 2256), false);
+return retVal;
+}
+
+static UA_StatusCode function_ua_namespace0_111_finish(UA_Server *server, UA_UInt16* ns) {
+
+return UA_Server_addNode_finish(server,
+UA_NODEID_NUMERIC(ns[0], 2993)
+);
+}
+
+/* Argument - ns=0;i=296 */
+
+static UA_StatusCode function_ua_namespace0_112_begin(UA_Server *server, UA_UInt16* ns) {
+
+UA_StatusCode retVal = UA_STATUSCODE_GOOD;
+UA_DataTypeAttributes attr = UA_DataTypeAttributes_default;
+attr.displayName = UA_LOCALIZEDTEXT("", "Argument");
+attr.description = UA_LOCALIZEDTEXT("", "An argument for a method.");
+attr.writeMask = 0;
+attr.userWriteMask = 0;
+retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_DATATYPE,
+UA_NODEID_NUMERIC(ns[0], 296),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_QUALIFIEDNAME(ns[0], "Argument"),
+UA_NODEID_NULL,
+(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_DATATYPEATTRIBUTES],NULL, NULL);
+retVal |= UA_Server_addReference(server, UA_NODEID_NUMERIC(ns[0], 296), UA_NODEID_NUMERIC(ns[0], 45), UA_EXPANDEDNODEID_NUMERIC(ns[0], 22), false);
+return retVal;
+}
+
+static UA_StatusCode function_ua_namespace0_112_finish(UA_Server *server, UA_UInt16* ns) {
+
+return UA_Server_addNode_finish(server,
+UA_NODEID_NUMERIC(ns[0], 296)
+);
+}
+
+/* Default Binary - ns=0;i=298 */
+
+static UA_StatusCode function_ua_namespace0_113_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.description = UA_LOCALIZEDTEXT("", "");
+attr.writeMask = 0;
+attr.userWriteMask = 0;
+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),
+(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], 39), UA_EXPANDEDNODEID_NUMERIC(ns[0], 7650), true);
+retVal |= UA_Server_addReference(server, UA_NODEID_NUMERIC(ns[0], 298), UA_NODEID_NUMERIC(ns[0], 38), UA_EXPANDEDNODEID_NUMERIC(ns[0], 296), false);
+return retVal;
+}
+
+static UA_StatusCode function_ua_namespace0_113_finish(UA_Server *server, UA_UInt16* ns) {
+
+return UA_Server_addNode_finish(server,
+UA_NODEID_NUMERIC(ns[0], 298)
+);
+}
+
+/* OutputArguments - ns=0;i=11494 */
+
+static UA_StatusCode function_ua_namespace0_114_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;
+attr.arrayDimensions = (UA_UInt32 *)UA_Array_new(1, &UA_TYPES[UA_TYPES_UINT32]);
+if (!attr.arrayDimensions) return UA_STATUSCODE_BADOUTOFMEMORY;
+attr.arrayDimensions[0] = 0;
+attr.dataType = UA_NODEID_NUMERIC(ns[0], 296);
+
+struct {
+ UA_String Name;
+ UA_NodeId DataType;
+ UA_Int32 ValueRank;
+ UA_Int32 ArrayDimensionsSize;
+ UA_UInt32 *ArrayDimensions;
+ UA_LocalizedText Description;
+} variablenode_ns_0_i_11494_Argument_0_0_struct;
+UA_ExtensionObject *variablenode_ns_0_i_11494_Argument_0_0 = UA_ExtensionObject_new();
+if (!variablenode_ns_0_i_11494_Argument_0_0) return UA_STATUSCODE_BADOUTOFMEMORY;
+variablenode_ns_0_i_11494_Argument_0_0_struct.Name = UA_STRING("ServerHandles");
+variablenode_ns_0_i_11494_Argument_0_0_struct.DataType = UA_NODEID_NUMERIC(ns[0], 7);
+variablenode_ns_0_i_11494_Argument_0_0_struct.ValueRank = (UA_Int32) 1;
+variablenode_ns_0_i_11494_Argument_0_0_struct.ArrayDimensionsSize = 1;
+variablenode_ns_0_i_11494_Argument_0_0_struct.ArrayDimensions = (UA_UInt32*) UA_malloc(sizeof(UA_UInt32));
+if (!variablenode_ns_0_i_11494_Argument_0_0_struct.ArrayDimensions) return UA_STATUSCODE_BADOUTOFMEMORY;
+variablenode_ns_0_i_11494_Argument_0_0_struct.ArrayDimensions[0] = (UA_UInt32) 0;
+variablenode_ns_0_i_11494_Argument_0_0_struct.Description = UA_LOCALIZEDTEXT("", "");
+variablenode_ns_0_i_11494_Argument_0_0->encoding = UA_EXTENSIONOBJECT_ENCODED_BYTESTRING;
+variablenode_ns_0_i_11494_Argument_0_0->content.encoded.typeId = UA_NODEID_NUMERIC(0, 298);
+retVal |= UA_ByteString_allocBuffer(&variablenode_ns_0_i_11494_Argument_0_0->content.encoded.body, 65000);
+UA_Byte *posvariablenode_ns_0_i_11494_Argument_0_0 = variablenode_ns_0_i_11494_Argument_0_0->content.encoded.body.data;
+const UA_Byte *endvariablenode_ns_0_i_11494_Argument_0_0 = &variablenode_ns_0_i_11494_Argument_0_0->content.encoded.body.data[65000];
+{
+retVal |= UA_encodeBinary(&variablenode_ns_0_i_11494_Argument_0_0_struct.Name, &UA_TYPES[UA_TYPES_STRING], &posvariablenode_ns_0_i_11494_Argument_0_0, &endvariablenode_ns_0_i_11494_Argument_0_0, NULL, NULL);
+retVal |= UA_encodeBinary(&variablenode_ns_0_i_11494_Argument_0_0_struct.DataType, &UA_TYPES[UA_TYPES_NODEID], &posvariablenode_ns_0_i_11494_Argument_0_0, &endvariablenode_ns_0_i_11494_Argument_0_0, NULL, NULL);
+retVal |= UA_encodeBinary(&variablenode_ns_0_i_11494_Argument_0_0_struct.ValueRank, &UA_TYPES[UA_TYPES_INT32], &posvariablenode_ns_0_i_11494_Argument_0_0, &endvariablenode_ns_0_i_11494_Argument_0_0, NULL, NULL);
+retVal |= UA_encodeBinary(&variablenode_ns_0_i_11494_Argument_0_0_struct.ArrayDimensions[0], &UA_TYPES[UA_TYPES_UINT32], &posvariablenode_ns_0_i_11494_Argument_0_0, &endvariablenode_ns_0_i_11494_Argument_0_0, NULL, NULL);
+retVal |= UA_encodeBinary(&variablenode_ns_0_i_11494_Argument_0_0_struct.Description, &UA_TYPES[UA_TYPES_LOCALIZEDTEXT], &posvariablenode_ns_0_i_11494_Argument_0_0, &endvariablenode_ns_0_i_11494_Argument_0_0, NULL, NULL);
+}
+size_t variablenode_ns_0_i_11494_Argument_0_0_encOffset = (uintptr_t)(posvariablenode_ns_0_i_11494_Argument_0_0-variablenode_ns_0_i_11494_Argument_0_0->content.encoded.body.data);
+variablenode_ns_0_i_11494_Argument_0_0->content.encoded.body.length = variablenode_ns_0_i_11494_Argument_0_0_encOffset;
+UA_Byte *variablenode_ns_0_i_11494_Argument_0_0_newBody = (UA_Byte *) UA_malloc(variablenode_ns_0_i_11494_Argument_0_0_encOffset);
+if (!variablenode_ns_0_i_11494_Argument_0_0_newBody) return UA_STATUSCODE_BADOUTOFMEMORY;
+memcpy(variablenode_ns_0_i_11494_Argument_0_0_newBody, variablenode_ns_0_i_11494_Argument_0_0->content.encoded.body.data, variablenode_ns_0_i_11494_Argument_0_0_encOffset);
+UA_Byte *variablenode_ns_0_i_11494_Argument_0_0_oldBody = variablenode_ns_0_i_11494_Argument_0_0->content.encoded.body.data;
+variablenode_ns_0_i_11494_Argument_0_0->content.encoded.body.data = variablenode_ns_0_i_11494_Argument_0_0_newBody;
+UA_free(variablenode_ns_0_i_11494_Argument_0_0_oldBody);
+
+
+struct {
+ UA_String Name;
+ UA_NodeId DataType;
+ UA_Int32 ValueRank;
+ UA_Int32 ArrayDimensionsSize;
+ UA_UInt32 *ArrayDimensions;
+ UA_LocalizedText Description;
+} variablenode_ns_0_i_11494_Argument_1_0_struct;
+UA_ExtensionObject *variablenode_ns_0_i_11494_Argument_1_0 = UA_ExtensionObject_new();
+if (!variablenode_ns_0_i_11494_Argument_1_0) return UA_STATUSCODE_BADOUTOFMEMORY;
+variablenode_ns_0_i_11494_Argument_1_0_struct.Name = UA_STRING("ClientHandles");
+variablenode_ns_0_i_11494_Argument_1_0_struct.DataType = UA_NODEID_NUMERIC(ns[0], 7);
+variablenode_ns_0_i_11494_Argument_1_0_struct.ValueRank = (UA_Int32) 1;
+variablenode_ns_0_i_11494_Argument_1_0_struct.ArrayDimensionsSize = 1;
+variablenode_ns_0_i_11494_Argument_1_0_struct.ArrayDimensions = (UA_UInt32*) UA_malloc(sizeof(UA_UInt32));
+if (!variablenode_ns_0_i_11494_Argument_1_0_struct.ArrayDimensions) return UA_STATUSCODE_BADOUTOFMEMORY;
+variablenode_ns_0_i_11494_Argument_1_0_struct.ArrayDimensions[0] = (UA_UInt32) 0;
+variablenode_ns_0_i_11494_Argument_1_0_struct.Description = UA_LOCALIZEDTEXT("", "");
+variablenode_ns_0_i_11494_Argument_1_0->encoding = UA_EXTENSIONOBJECT_ENCODED_BYTESTRING;
+variablenode_ns_0_i_11494_Argument_1_0->content.encoded.typeId = UA_NODEID_NUMERIC(0, 298);
+retVal |= UA_ByteString_allocBuffer(&variablenode_ns_0_i_11494_Argument_1_0->content.encoded.body, 65000);
+UA_Byte *posvariablenode_ns_0_i_11494_Argument_1_0 = variablenode_ns_0_i_11494_Argument_1_0->content.encoded.body.data;
+const UA_Byte *endvariablenode_ns_0_i_11494_Argument_1_0 = &variablenode_ns_0_i_11494_Argument_1_0->content.encoded.body.data[65000];
+{
+retVal |= UA_encodeBinary(&variablenode_ns_0_i_11494_Argument_1_0_struct.Name, &UA_TYPES[UA_TYPES_STRING], &posvariablenode_ns_0_i_11494_Argument_1_0, &endvariablenode_ns_0_i_11494_Argument_1_0, NULL, NULL);
+retVal |= UA_encodeBinary(&variablenode_ns_0_i_11494_Argument_1_0_struct.DataType, &UA_TYPES[UA_TYPES_NODEID], &posvariablenode_ns_0_i_11494_Argument_1_0, &endvariablenode_ns_0_i_11494_Argument_1_0, NULL, NULL);
+retVal |= UA_encodeBinary(&variablenode_ns_0_i_11494_Argument_1_0_struct.ValueRank, &UA_TYPES[UA_TYPES_INT32], &posvariablenode_ns_0_i_11494_Argument_1_0, &endvariablenode_ns_0_i_11494_Argument_1_0, NULL, NULL);
+retVal |= UA_encodeBinary(&variablenode_ns_0_i_11494_Argument_1_0_struct.ArrayDimensions[0], &UA_TYPES[UA_TYPES_UINT32], &posvariablenode_ns_0_i_11494_Argument_1_0, &endvariablenode_ns_0_i_11494_Argument_1_0, NULL, NULL);
+retVal |= UA_encodeBinary(&variablenode_ns_0_i_11494_Argument_1_0_struct.Description, &UA_TYPES[UA_TYPES_LOCALIZEDTEXT], &posvariablenode_ns_0_i_11494_Argument_1_0, &endvariablenode_ns_0_i_11494_Argument_1_0, NULL, NULL);
+}
+size_t variablenode_ns_0_i_11494_Argument_1_0_encOffset = (uintptr_t)(posvariablenode_ns_0_i_11494_Argument_1_0-variablenode_ns_0_i_11494_Argument_1_0->content.encoded.body.data);
+variablenode_ns_0_i_11494_Argument_1_0->content.encoded.body.length = variablenode_ns_0_i_11494_Argument_1_0_encOffset;
+UA_Byte *variablenode_ns_0_i_11494_Argument_1_0_newBody = (UA_Byte *) UA_malloc(variablenode_ns_0_i_11494_Argument_1_0_encOffset);
+if (!variablenode_ns_0_i_11494_Argument_1_0_newBody) return UA_STATUSCODE_BADOUTOFMEMORY;
+memcpy(variablenode_ns_0_i_11494_Argument_1_0_newBody, variablenode_ns_0_i_11494_Argument_1_0->content.encoded.body.data, variablenode_ns_0_i_11494_Argument_1_0_encOffset);
+UA_Byte *variablenode_ns_0_i_11494_Argument_1_0_oldBody = variablenode_ns_0_i_11494_Argument_1_0->content.encoded.body.data;
+variablenode_ns_0_i_11494_Argument_1_0->content.encoded.body.data = variablenode_ns_0_i_11494_Argument_1_0_newBody;
+UA_free(variablenode_ns_0_i_11494_Argument_1_0_oldBody);
+
+UA_ExtensionObject variablenode_ns_0_i_11494_variant_DataContents[2];
+variablenode_ns_0_i_11494_variant_DataContents[0] = *variablenode_ns_0_i_11494_Argument_0_0;
+variablenode_ns_0_i_11494_variant_DataContents[1] = *variablenode_ns_0_i_11494_Argument_1_0;
+UA_Variant_setArray(&attr.value, &variablenode_ns_0_i_11494_variant_DataContents, (UA_Int32) 2, &UA_TYPES[UA_TYPES_EXTENSIONOBJECT]);
+attr.displayName = UA_LOCALIZEDTEXT("", "OutputArguments");
+attr.description = UA_LOCALIZEDTEXT("", "");
+attr.writeMask = 0;
+attr.userWriteMask = 0;
+retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_VARIABLE,
+UA_NODEID_NUMERIC(ns[0], 11494),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_QUALIFIEDNAME(ns[0], "OutputArguments"),
+UA_NODEID_NUMERIC(ns[0], 68),
+(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
+UA_Array_delete(attr.arrayDimensions, 1, &UA_TYPES[UA_TYPES_UINT32]);
+
+UA_ExtensionObject_delete(variablenode_ns_0_i_11494_Argument_0_0);
+UA_free(variablenode_ns_0_i_11494_Argument_0_0_struct.ArrayDimensions);
+
+UA_ExtensionObject_delete(variablenode_ns_0_i_11494_Argument_1_0);
+UA_free(variablenode_ns_0_i_11494_Argument_1_0_struct.ArrayDimensions);
+retVal |= UA_Server_addReference(server, UA_NODEID_NUMERIC(ns[0], 11494), UA_NODEID_NUMERIC(ns[0], 46), UA_EXPANDEDNODEID_NUMERIC(ns[0], 11492), false);
+return retVal;
+}
+
+static UA_StatusCode function_ua_namespace0_114_finish(UA_Server *server, UA_UInt16* ns) {
+
+return UA_Server_addNode_finish(server,
+UA_NODEID_NUMERIC(ns[0], 11494)
+);
+}
+
+/* InputArguments - ns=0;i=11493 */
+
+static UA_StatusCode function_ua_namespace0_115_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;
+attr.arrayDimensions = (UA_UInt32 *)UA_Array_new(1, &UA_TYPES[UA_TYPES_UINT32]);
+if (!attr.arrayDimensions) return UA_STATUSCODE_BADOUTOFMEMORY;
+attr.arrayDimensions[0] = 0;
+attr.dataType = UA_NODEID_NUMERIC(ns[0], 296);
+
+struct {
+ UA_String Name;
+ UA_NodeId DataType;
+ UA_Int32 ValueRank;
+ UA_Int32 ArrayDimensionsSize;
+ UA_UInt32 *ArrayDimensions;
+ UA_LocalizedText Description;
+} variablenode_ns_0_i_11493_Argument_0_0_struct;
+UA_ExtensionObject *variablenode_ns_0_i_11493_Argument_0_0 = UA_ExtensionObject_new();
+if (!variablenode_ns_0_i_11493_Argument_0_0) return UA_STATUSCODE_BADOUTOFMEMORY;
+variablenode_ns_0_i_11493_Argument_0_0_struct.Name = UA_STRING("SubscriptionId");
+variablenode_ns_0_i_11493_Argument_0_0_struct.DataType = UA_NODEID_NUMERIC(ns[0], 7);
+variablenode_ns_0_i_11493_Argument_0_0_struct.ValueRank = (UA_Int32) -1;
+variablenode_ns_0_i_11493_Argument_0_0_struct.ArrayDimensionsSize = 1;
+variablenode_ns_0_i_11493_Argument_0_0_struct.ArrayDimensions = (UA_UInt32*) UA_malloc(sizeof(UA_UInt32));
+if (!variablenode_ns_0_i_11493_Argument_0_0_struct.ArrayDimensions) return UA_STATUSCODE_BADOUTOFMEMORY;
+variablenode_ns_0_i_11493_Argument_0_0_struct.ArrayDimensions[0] = (UA_UInt32) 0;
+variablenode_ns_0_i_11493_Argument_0_0_struct.Description = UA_LOCALIZEDTEXT("", "");
+variablenode_ns_0_i_11493_Argument_0_0->encoding = UA_EXTENSIONOBJECT_ENCODED_BYTESTRING;
+variablenode_ns_0_i_11493_Argument_0_0->content.encoded.typeId = UA_NODEID_NUMERIC(0, 298);
+retVal |= UA_ByteString_allocBuffer(&variablenode_ns_0_i_11493_Argument_0_0->content.encoded.body, 65000);
+UA_Byte *posvariablenode_ns_0_i_11493_Argument_0_0 = variablenode_ns_0_i_11493_Argument_0_0->content.encoded.body.data;
+const UA_Byte *endvariablenode_ns_0_i_11493_Argument_0_0 = &variablenode_ns_0_i_11493_Argument_0_0->content.encoded.body.data[65000];
+{
+retVal |= UA_encodeBinary(&variablenode_ns_0_i_11493_Argument_0_0_struct.Name, &UA_TYPES[UA_TYPES_STRING], &posvariablenode_ns_0_i_11493_Argument_0_0, &endvariablenode_ns_0_i_11493_Argument_0_0, NULL, NULL);
+retVal |= UA_encodeBinary(&variablenode_ns_0_i_11493_Argument_0_0_struct.DataType, &UA_TYPES[UA_TYPES_NODEID], &posvariablenode_ns_0_i_11493_Argument_0_0, &endvariablenode_ns_0_i_11493_Argument_0_0, NULL, NULL);
+retVal |= UA_encodeBinary(&variablenode_ns_0_i_11493_Argument_0_0_struct.ValueRank, &UA_TYPES[UA_TYPES_INT32], &posvariablenode_ns_0_i_11493_Argument_0_0, &endvariablenode_ns_0_i_11493_Argument_0_0, NULL, NULL);
+retVal |= UA_encodeBinary(&variablenode_ns_0_i_11493_Argument_0_0_struct.ArrayDimensions[0], &UA_TYPES[UA_TYPES_UINT32], &posvariablenode_ns_0_i_11493_Argument_0_0, &endvariablenode_ns_0_i_11493_Argument_0_0, NULL, NULL);
+retVal |= UA_encodeBinary(&variablenode_ns_0_i_11493_Argument_0_0_struct.Description, &UA_TYPES[UA_TYPES_LOCALIZEDTEXT], &posvariablenode_ns_0_i_11493_Argument_0_0, &endvariablenode_ns_0_i_11493_Argument_0_0, NULL, NULL);
+}
+size_t variablenode_ns_0_i_11493_Argument_0_0_encOffset = (uintptr_t)(posvariablenode_ns_0_i_11493_Argument_0_0-variablenode_ns_0_i_11493_Argument_0_0->content.encoded.body.data);
+variablenode_ns_0_i_11493_Argument_0_0->content.encoded.body.length = variablenode_ns_0_i_11493_Argument_0_0_encOffset;
+UA_Byte *variablenode_ns_0_i_11493_Argument_0_0_newBody = (UA_Byte *) UA_malloc(variablenode_ns_0_i_11493_Argument_0_0_encOffset);
+if (!variablenode_ns_0_i_11493_Argument_0_0_newBody) return UA_STATUSCODE_BADOUTOFMEMORY;
+memcpy(variablenode_ns_0_i_11493_Argument_0_0_newBody, variablenode_ns_0_i_11493_Argument_0_0->content.encoded.body.data, variablenode_ns_0_i_11493_Argument_0_0_encOffset);
+UA_Byte *variablenode_ns_0_i_11493_Argument_0_0_oldBody = variablenode_ns_0_i_11493_Argument_0_0->content.encoded.body.data;
+variablenode_ns_0_i_11493_Argument_0_0->content.encoded.body.data = variablenode_ns_0_i_11493_Argument_0_0_newBody;
+UA_free(variablenode_ns_0_i_11493_Argument_0_0_oldBody);
+
+UA_ExtensionObject variablenode_ns_0_i_11493_variant_DataContents[1];
+variablenode_ns_0_i_11493_variant_DataContents[0] = *variablenode_ns_0_i_11493_Argument_0_0;
+UA_Variant_setArray(&attr.value, &variablenode_ns_0_i_11493_variant_DataContents, (UA_Int32) 1, &UA_TYPES[UA_TYPES_EXTENSIONOBJECT]);
+attr.displayName = UA_LOCALIZEDTEXT("", "InputArguments");
+attr.description = UA_LOCALIZEDTEXT("", "");
+attr.writeMask = 0;
+attr.userWriteMask = 0;
+retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_VARIABLE,
+UA_NODEID_NUMERIC(ns[0], 11493),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_QUALIFIEDNAME(ns[0], "InputArguments"),
+UA_NODEID_NUMERIC(ns[0], 68),
+(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
+UA_Array_delete(attr.arrayDimensions, 1, &UA_TYPES[UA_TYPES_UINT32]);
+
+UA_ExtensionObject_delete(variablenode_ns_0_i_11493_Argument_0_0);
+UA_free(variablenode_ns_0_i_11493_Argument_0_0_struct.ArrayDimensions);
+retVal |= UA_Server_addReference(server, UA_NODEID_NUMERIC(ns[0], 11493), UA_NODEID_NUMERIC(ns[0], 46), UA_EXPANDEDNODEID_NUMERIC(ns[0], 11492), false);
+return retVal;
+}
+
+static UA_StatusCode function_ua_namespace0_115_finish(UA_Server *server, UA_UInt16* ns) {
+
+return UA_Server_addNode_finish(server,
+UA_NODEID_NUMERIC(ns[0], 11493)
+);
+}
+
+/* Default XML - ns=0;i=3063 */
+
+static UA_StatusCode function_ua_namespace0_116_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");
+attr.description = UA_LOCALIZEDTEXT("", "The default XML encoding for a data type.");
+attr.writeMask = 0;
+attr.userWriteMask = 0;
+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_QUALIFIEDNAME(ns[0], "Default XML"),
+UA_NODEID_NUMERIC(ns[0], 58),
+(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_OBJECTATTRIBUTES],NULL, NULL);
+return retVal;
+}
+
+static UA_StatusCode function_ua_namespace0_116_finish(UA_Server *server, UA_UInt16* ns) {
+
+return UA_Server_addNode_finish(server,
+UA_NODEID_NUMERIC(ns[0], 3063)
+);
+}
+
+/* Default Binary - ns=0;i=3062 */
+
+static UA_StatusCode function_ua_namespace0_117_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.description = UA_LOCALIZEDTEXT("", "The default binary encoding for a data type.");
+attr.writeMask = 0;
+attr.userWriteMask = 0;
+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_QUALIFIEDNAME(ns[0], "Default Binary"),
+UA_NODEID_NUMERIC(ns[0], 58),
+(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_OBJECTATTRIBUTES],NULL, NULL);
+return retVal;
+}
+
+static UA_StatusCode function_ua_namespace0_117_finish(UA_Server *server, UA_UInt16* ns) {
+
+return UA_Server_addNode_finish(server,
+UA_NODEID_NUMERIC(ns[0], 3062)
+);
+}
+
+/* ServerDiagnosticsType - ns=0;i=2020 */
+
+static UA_StatusCode function_ua_namespace0_118_begin(UA_Server *server, UA_UInt16* ns) {
+
+UA_StatusCode retVal = UA_STATUSCODE_GOOD;
+UA_ObjectTypeAttributes attr = UA_ObjectTypeAttributes_default;
+attr.displayName = UA_LOCALIZEDTEXT("", "ServerDiagnosticsType");
+attr.description = UA_LOCALIZEDTEXT("", "The diagnostics information for a server.");
+attr.writeMask = 0;
+attr.userWriteMask = 0;
+retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_OBJECTTYPE,
+UA_NODEID_NUMERIC(ns[0], 2020),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_QUALIFIEDNAME(ns[0], "ServerDiagnosticsType"),
+UA_NODEID_NULL,
+(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_OBJECTTYPEATTRIBUTES],NULL, NULL);
+retVal |= UA_Server_addReference(server, UA_NODEID_NUMERIC(ns[0], 2020), UA_NODEID_NUMERIC(ns[0], 45), UA_EXPANDEDNODEID_NUMERIC(ns[0], 58), false);
+return retVal;
+}
+
+static UA_StatusCode function_ua_namespace0_118_finish(UA_Server *server, UA_UInt16* ns) {
+
+return UA_Server_addNode_finish(server,
+UA_NODEID_NUMERIC(ns[0], 2020)
+);
+}
+
+/* ServerDiagnostics - ns=0;i=2274 */
+
+static UA_StatusCode function_ua_namespace0_119_begin(UA_Server *server, UA_UInt16* ns) {
+
+UA_StatusCode retVal = UA_STATUSCODE_GOOD;
+UA_ObjectAttributes attr = UA_ObjectAttributes_default;
+attr.displayName = UA_LOCALIZEDTEXT("", "ServerDiagnostics");
+attr.description = UA_LOCALIZEDTEXT("", "Reports diagnostics about the server.");
+attr.writeMask = 0;
+attr.userWriteMask = 0;
+retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_OBJECT,
+UA_NODEID_NUMERIC(ns[0], 2274),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_QUALIFIEDNAME(ns[0], "ServerDiagnostics"),
+UA_NODEID_NUMERIC(ns[0], 2020),
+(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_OBJECTATTRIBUTES],NULL, NULL);
+retVal |= UA_Server_addReference(server, UA_NODEID_NUMERIC(ns[0], 2274), UA_NODEID_NUMERIC(ns[0], 47), UA_EXPANDEDNODEID_NUMERIC(ns[0], 2253), false);
+return retVal;
+}
+
+static UA_StatusCode function_ua_namespace0_119_finish(UA_Server *server, UA_UInt16* ns) {
+
+return UA_Server_addNode_finish(server,
+UA_NODEID_NUMERIC(ns[0], 2274)
+);
+}
+
+/* ServerDiagnosticsSummary - ns=0;i=2275 */
+
+static UA_StatusCode function_ua_namespace0_120_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.dataType = UA_NODEID_NUMERIC(ns[0], 859);
+UA_Variant_setScalar(&attr.value, NULL, &UA_TYPES[UA_TYPES_SERVERDIAGNOSTICSSUMMARYDATATYPE]);
+attr.displayName = UA_LOCALIZEDTEXT("", "ServerDiagnosticsSummary");
+attr.description = UA_LOCALIZEDTEXT("", "A summary of server level diagnostics.");
+attr.writeMask = 0;
+attr.userWriteMask = 0;
+retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_VARIABLE,
+UA_NODEID_NUMERIC(ns[0], 2275),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_QUALIFIEDNAME(ns[0], "ServerDiagnosticsSummary"),
+UA_NODEID_NUMERIC(ns[0], 2150),
+(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
+retVal |= UA_Server_addReference(server, UA_NODEID_NUMERIC(ns[0], 2275), UA_NODEID_NUMERIC(ns[0], 47), UA_EXPANDEDNODEID_NUMERIC(ns[0], 2274), false);
+return retVal;
+}
+
+static UA_StatusCode function_ua_namespace0_120_finish(UA_Server *server, UA_UInt16* ns) {
+
+return UA_Server_addNode_finish(server,
+UA_NODEID_NUMERIC(ns[0], 2275)
+);
+}
+
+/* SecurityRejectedRequestsCount - ns=0;i=2287 */
+
+static UA_StatusCode function_ua_namespace0_121_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.dataType = UA_NODEID_NUMERIC(ns[0], 7);
+UA_Variant_setScalar(&attr.value, NULL, &UA_TYPES[UA_TYPES_UINT32]);
+attr.displayName = UA_LOCALIZEDTEXT("", "SecurityRejectedRequestsCount");
+attr.description = UA_LOCALIZEDTEXT("", "");
+attr.writeMask = 0;
+attr.userWriteMask = 0;
+retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_VARIABLE,
+UA_NODEID_NUMERIC(ns[0], 2287),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_QUALIFIEDNAME(ns[0], "SecurityRejectedRequestsCount"),
+UA_NODEID_NUMERIC(ns[0], 63),
+(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
+retVal |= UA_Server_addReference(server, UA_NODEID_NUMERIC(ns[0], 2287), UA_NODEID_NUMERIC(ns[0], 47), UA_EXPANDEDNODEID_NUMERIC(ns[0], 2275), false);
+return retVal;
+}
+
+static UA_StatusCode function_ua_namespace0_121_finish(UA_Server *server, UA_UInt16* ns) {
+
+return UA_Server_addNode_finish(server,
+UA_NODEID_NUMERIC(ns[0], 2287)
+);
+}
+
+/* CumulatedSubscriptionCount - ns=0;i=2286 */
+
+static UA_StatusCode function_ua_namespace0_122_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.dataType = UA_NODEID_NUMERIC(ns[0], 7);
+UA_Variant_setScalar(&attr.value, NULL, &UA_TYPES[UA_TYPES_UINT32]);
+attr.displayName = UA_LOCALIZEDTEXT("", "CumulatedSubscriptionCount");
+attr.description = UA_LOCALIZEDTEXT("", "");
+attr.writeMask = 0;
+attr.userWriteMask = 0;
+retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_VARIABLE,
+UA_NODEID_NUMERIC(ns[0], 2286),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_QUALIFIEDNAME(ns[0], "CumulatedSubscriptionCount"),
+UA_NODEID_NUMERIC(ns[0], 63),
+(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
+retVal |= UA_Server_addReference(server, UA_NODEID_NUMERIC(ns[0], 2286), UA_NODEID_NUMERIC(ns[0], 47), UA_EXPANDEDNODEID_NUMERIC(ns[0], 2275), false);
+return retVal;
+}
+
+static UA_StatusCode function_ua_namespace0_122_finish(UA_Server *server, UA_UInt16* ns) {
+
+return UA_Server_addNode_finish(server,
+UA_NODEID_NUMERIC(ns[0], 2286)
+);
+}
+
+/* CurrentSubscriptionCount - ns=0;i=2285 */
+
+static UA_StatusCode function_ua_namespace0_123_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.dataType = UA_NODEID_NUMERIC(ns[0], 7);
+UA_Variant_setScalar(&attr.value, NULL, &UA_TYPES[UA_TYPES_UINT32]);
+attr.displayName = UA_LOCALIZEDTEXT("", "CurrentSubscriptionCount");
+attr.description = UA_LOCALIZEDTEXT("", "");
+attr.writeMask = 0;
+attr.userWriteMask = 0;
+retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_VARIABLE,
+UA_NODEID_NUMERIC(ns[0], 2285),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_QUALIFIEDNAME(ns[0], "CurrentSubscriptionCount"),
+UA_NODEID_NUMERIC(ns[0], 63),
+(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
+retVal |= UA_Server_addReference(server, UA_NODEID_NUMERIC(ns[0], 2285), UA_NODEID_NUMERIC(ns[0], 47), UA_EXPANDEDNODEID_NUMERIC(ns[0], 2275), false);
+return retVal;
+}
+
+static UA_StatusCode function_ua_namespace0_123_finish(UA_Server *server, UA_UInt16* ns) {
+
+return UA_Server_addNode_finish(server,
+UA_NODEID_NUMERIC(ns[0], 2285)
+);
+}
+
+/* PublishingIntervalCount - ns=0;i=2284 */
+
+static UA_StatusCode function_ua_namespace0_124_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.dataType = UA_NODEID_NUMERIC(ns[0], 7);
+UA_Variant_setScalar(&attr.value, NULL, &UA_TYPES[UA_TYPES_UINT32]);
+attr.displayName = UA_LOCALIZEDTEXT("", "PublishingIntervalCount");
+attr.description = UA_LOCALIZEDTEXT("", "");
+attr.writeMask = 0;
+attr.userWriteMask = 0;
+retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_VARIABLE,
+UA_NODEID_NUMERIC(ns[0], 2284),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_QUALIFIEDNAME(ns[0], "PublishingIntervalCount"),
+UA_NODEID_NUMERIC(ns[0], 63),
+(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
+retVal |= UA_Server_addReference(server, UA_NODEID_NUMERIC(ns[0], 2284), UA_NODEID_NUMERIC(ns[0], 47), UA_EXPANDEDNODEID_NUMERIC(ns[0], 2275), false);
+return retVal;
+}
+
+static UA_StatusCode function_ua_namespace0_124_finish(UA_Server *server, UA_UInt16* ns) {
+
+return UA_Server_addNode_finish(server,
+UA_NODEID_NUMERIC(ns[0], 2284)
+);
+}
+
+/* SessionAbortCount - ns=0;i=2282 */
+
+static UA_StatusCode function_ua_namespace0_125_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.dataType = UA_NODEID_NUMERIC(ns[0], 7);
+UA_Variant_setScalar(&attr.value, NULL, &UA_TYPES[UA_TYPES_UINT32]);
+attr.displayName = UA_LOCALIZEDTEXT("", "SessionAbortCount");
+attr.description = UA_LOCALIZEDTEXT("", "");
+attr.writeMask = 0;
+attr.userWriteMask = 0;
+retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_VARIABLE,
+UA_NODEID_NUMERIC(ns[0], 2282),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_QUALIFIEDNAME(ns[0], "SessionAbortCount"),
+UA_NODEID_NUMERIC(ns[0], 63),
+(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
+retVal |= UA_Server_addReference(server, UA_NODEID_NUMERIC(ns[0], 2282), UA_NODEID_NUMERIC(ns[0], 47), UA_EXPANDEDNODEID_NUMERIC(ns[0], 2275), false);
+return retVal;
+}
+
+static UA_StatusCode function_ua_namespace0_125_finish(UA_Server *server, UA_UInt16* ns) {
+
+return UA_Server_addNode_finish(server,
+UA_NODEID_NUMERIC(ns[0], 2282)
+);
+}
+
+/* SessionTimeoutCount - ns=0;i=2281 */
+
+static UA_StatusCode function_ua_namespace0_126_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.dataType = UA_NODEID_NUMERIC(ns[0], 7);
+UA_Variant_setScalar(&attr.value, NULL, &UA_TYPES[UA_TYPES_UINT32]);
+attr.displayName = UA_LOCALIZEDTEXT("", "SessionTimeoutCount");
+attr.description = UA_LOCALIZEDTEXT("", "");
+attr.writeMask = 0;
+attr.userWriteMask = 0;
+retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_VARIABLE,
+UA_NODEID_NUMERIC(ns[0], 2281),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_QUALIFIEDNAME(ns[0], "SessionTimeoutCount"),
+UA_NODEID_NUMERIC(ns[0], 63),
+(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
+retVal |= UA_Server_addReference(server, UA_NODEID_NUMERIC(ns[0], 2281), UA_NODEID_NUMERIC(ns[0], 47), UA_EXPANDEDNODEID_NUMERIC(ns[0], 2275), false);
+return retVal;
+}
+
+static UA_StatusCode function_ua_namespace0_126_finish(UA_Server *server, UA_UInt16* ns) {
+
+return UA_Server_addNode_finish(server,
+UA_NODEID_NUMERIC(ns[0], 2281)
+);
+}
+
+/* RejectedSessionCount - ns=0;i=3705 */
+
+static UA_StatusCode function_ua_namespace0_127_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.dataType = UA_NODEID_NUMERIC(ns[0], 7);
+UA_Variant_setScalar(&attr.value, NULL, &UA_TYPES[UA_TYPES_UINT32]);
+attr.displayName = UA_LOCALIZEDTEXT("", "RejectedSessionCount");
+attr.description = UA_LOCALIZEDTEXT("", "");
+attr.writeMask = 0;
+attr.userWriteMask = 0;
+retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_VARIABLE,
+UA_NODEID_NUMERIC(ns[0], 3705),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_QUALIFIEDNAME(ns[0], "RejectedSessionCount"),
+UA_NODEID_NUMERIC(ns[0], 63),
+(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
+retVal |= UA_Server_addReference(server, UA_NODEID_NUMERIC(ns[0], 3705), UA_NODEID_NUMERIC(ns[0], 47), UA_EXPANDEDNODEID_NUMERIC(ns[0], 2275), false);
+return retVal;
+}
+
+static UA_StatusCode function_ua_namespace0_127_finish(UA_Server *server, UA_UInt16* ns) {
+
+return UA_Server_addNode_finish(server,
+UA_NODEID_NUMERIC(ns[0], 3705)
+);
+}
+
+/* RejectedRequestsCount - ns=0;i=2288 */
+
+static UA_StatusCode function_ua_namespace0_128_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.dataType = UA_NODEID_NUMERIC(ns[0], 7);
+UA_Variant_setScalar(&attr.value, NULL, &UA_TYPES[UA_TYPES_UINT32]);
+attr.displayName = UA_LOCALIZEDTEXT("", "RejectedRequestsCount");
+attr.description = UA_LOCALIZEDTEXT("", "");
+attr.writeMask = 0;
+attr.userWriteMask = 0;
+retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_VARIABLE,
+UA_NODEID_NUMERIC(ns[0], 2288),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_QUALIFIEDNAME(ns[0], "RejectedRequestsCount"),
+UA_NODEID_NUMERIC(ns[0], 63),
+(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
+retVal |= UA_Server_addReference(server, UA_NODEID_NUMERIC(ns[0], 2288), UA_NODEID_NUMERIC(ns[0], 47), UA_EXPANDEDNODEID_NUMERIC(ns[0], 2275), false);
+return retVal;
+}
+
+static UA_StatusCode function_ua_namespace0_128_finish(UA_Server *server, UA_UInt16* ns) {
+
+return UA_Server_addNode_finish(server,
+UA_NODEID_NUMERIC(ns[0], 2288)
+);
+}
+
+/* ServerViewCount - ns=0;i=2276 */
+
+static UA_StatusCode function_ua_namespace0_129_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.dataType = UA_NODEID_NUMERIC(ns[0], 7);
+UA_Variant_setScalar(&attr.value, NULL, &UA_TYPES[UA_TYPES_UINT32]);
+attr.displayName = UA_LOCALIZEDTEXT("", "ServerViewCount");
+attr.description = UA_LOCALIZEDTEXT("", "");
+attr.writeMask = 0;
+attr.userWriteMask = 0;
+retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_VARIABLE,
+UA_NODEID_NUMERIC(ns[0], 2276),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_QUALIFIEDNAME(ns[0], "ServerViewCount"),
+UA_NODEID_NUMERIC(ns[0], 63),
+(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
+retVal |= UA_Server_addReference(server, UA_NODEID_NUMERIC(ns[0], 2276), UA_NODEID_NUMERIC(ns[0], 47), UA_EXPANDEDNODEID_NUMERIC(ns[0], 2275), false);
+return retVal;
+}
+
+static UA_StatusCode function_ua_namespace0_129_finish(UA_Server *server, UA_UInt16* ns) {
+
+return UA_Server_addNode_finish(server,
+UA_NODEID_NUMERIC(ns[0], 2276)
+);
+}
+
+/* CurrentSessionCount - ns=0;i=2277 */
+
+static UA_StatusCode function_ua_namespace0_130_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.dataType = UA_NODEID_NUMERIC(ns[0], 7);
+UA_Variant_setScalar(&attr.value, NULL, &UA_TYPES[UA_TYPES_UINT32]);
+attr.displayName = UA_LOCALIZEDTEXT("", "CurrentSessionCount");
+attr.description = UA_LOCALIZEDTEXT("", "");
+attr.writeMask = 0;
+attr.userWriteMask = 0;
+retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_VARIABLE,
+UA_NODEID_NUMERIC(ns[0], 2277),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_QUALIFIEDNAME(ns[0], "CurrentSessionCount"),
+UA_NODEID_NUMERIC(ns[0], 63),
+(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
+retVal |= UA_Server_addReference(server, UA_NODEID_NUMERIC(ns[0], 2277), UA_NODEID_NUMERIC(ns[0], 47), UA_EXPANDEDNODEID_NUMERIC(ns[0], 2275), false);
+return retVal;
+}
+
+static UA_StatusCode function_ua_namespace0_130_finish(UA_Server *server, UA_UInt16* ns) {
+
+return UA_Server_addNode_finish(server,
+UA_NODEID_NUMERIC(ns[0], 2277)
+);
+}
+
+/* CumulatedSessionCount - ns=0;i=2278 */
+
+static UA_StatusCode function_ua_namespace0_131_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.dataType = UA_NODEID_NUMERIC(ns[0], 7);
+UA_Variant_setScalar(&attr.value, NULL, &UA_TYPES[UA_TYPES_UINT32]);
+attr.displayName = UA_LOCALIZEDTEXT("", "CumulatedSessionCount");
+attr.description = UA_LOCALIZEDTEXT("", "");
+attr.writeMask = 0;
+attr.userWriteMask = 0;
+retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_VARIABLE,
+UA_NODEID_NUMERIC(ns[0], 2278),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_QUALIFIEDNAME(ns[0], "CumulatedSessionCount"),
+UA_NODEID_NUMERIC(ns[0], 63),
+(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
+retVal |= UA_Server_addReference(server, UA_NODEID_NUMERIC(ns[0], 2278), UA_NODEID_NUMERIC(ns[0], 47), UA_EXPANDEDNODEID_NUMERIC(ns[0], 2275), false);
+return retVal;
+}
+
+static UA_StatusCode function_ua_namespace0_131_finish(UA_Server *server, UA_UInt16* ns) {
+
+return UA_Server_addNode_finish(server,
+UA_NODEID_NUMERIC(ns[0], 2278)
+);
+}
+
+/* SecurityRejectedSessionCount - ns=0;i=2279 */
+
+static UA_StatusCode function_ua_namespace0_132_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.dataType = UA_NODEID_NUMERIC(ns[0], 7);
+UA_Variant_setScalar(&attr.value, NULL, &UA_TYPES[UA_TYPES_UINT32]);
+attr.displayName = UA_LOCALIZEDTEXT("", "SecurityRejectedSessionCount");
+attr.description = UA_LOCALIZEDTEXT("", "");
+attr.writeMask = 0;
+attr.userWriteMask = 0;
+retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_VARIABLE,
+UA_NODEID_NUMERIC(ns[0], 2279),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_QUALIFIEDNAME(ns[0], "SecurityRejectedSessionCount"),
+UA_NODEID_NUMERIC(ns[0], 63),
+(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
+retVal |= UA_Server_addReference(server, UA_NODEID_NUMERIC(ns[0], 2279), UA_NODEID_NUMERIC(ns[0], 47), UA_EXPANDEDNODEID_NUMERIC(ns[0], 2275), false);
+return retVal;
+}
+
+static UA_StatusCode function_ua_namespace0_132_finish(UA_Server *server, UA_UInt16* ns) {
+
+return UA_Server_addNode_finish(server,
+UA_NODEID_NUMERIC(ns[0], 2279)
+);
+}
+
+/* EnabledFlag - ns=0;i=2294 */
+
+static UA_StatusCode function_ua_namespace0_133_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 = 3;
+attr.valueRank = -1;
+attr.dataType = UA_NODEID_NUMERIC(ns[0], 1);
+UA_Variant_setScalar(&attr.value, NULL, &UA_TYPES[UA_TYPES_BOOLEAN]);
+attr.displayName = UA_LOCALIZEDTEXT("", "EnabledFlag");
+attr.description = UA_LOCALIZEDTEXT("", "If TRUE the diagnostics collection is enabled.");
+attr.writeMask = 0;
+attr.userWriteMask = 0;
+retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_VARIABLE,
+UA_NODEID_NUMERIC(ns[0], 2294),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_NODEID_NUMERIC(ns[0], 0),
+UA_QUALIFIEDNAME(ns[0], "EnabledFlag"),
+UA_NODEID_NUMERIC(ns[0], 68),
+(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
+retVal |= UA_Server_addReference(server, UA_NODEID_NUMERIC(ns[0], 2294), UA_NODEID_NUMERIC(ns[0], 46), UA_EXPANDEDNODEID_NUMERIC(ns[0], 2274), false);
+return retVal;
+}
+
+static UA_StatusCode function_ua_namespace0_133_finish(UA_Server *server, UA_UInt16* ns) {
+
+return UA_Server_addNode_finish(server,
+UA_NODEID_NUMERIC(ns[0], 2294)
+);
+}
+
+UA_StatusCode ua_namespace0(UA_Server *server) {
+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/");
+retVal |= function_ua_namespace0_0_begin(server, ns);
+retVal |= function_ua_namespace0_1_begin(server, ns);
+retVal |= function_ua_namespace0_2_begin(server, ns);
+retVal |= function_ua_namespace0_3_begin(server, ns);
+retVal |= function_ua_namespace0_4_begin(server, ns);
+retVal |= function_ua_namespace0_5_begin(server, ns);
+retVal |= function_ua_namespace0_6_begin(server, ns);
+retVal |= function_ua_namespace0_7_begin(server, ns);
+retVal |= function_ua_namespace0_8_begin(server, ns);
+retVal |= function_ua_namespace0_9_begin(server, ns);
+retVal |= function_ua_namespace0_10_begin(server, ns);
+retVal |= function_ua_namespace0_11_begin(server, ns);
+retVal |= function_ua_namespace0_12_begin(server, ns);
+retVal |= function_ua_namespace0_13_begin(server, ns);
+retVal |= function_ua_namespace0_14_begin(server, ns);
+retVal |= function_ua_namespace0_15_begin(server, ns);
+retVal |= function_ua_namespace0_16_begin(server, ns);
+retVal |= function_ua_namespace0_17_begin(server, ns);
+retVal |= function_ua_namespace0_18_begin(server, ns);
+retVal |= function_ua_namespace0_19_begin(server, ns);
+retVal |= function_ua_namespace0_20_begin(server, ns);
+retVal |= function_ua_namespace0_21_begin(server, ns);
+retVal |= function_ua_namespace0_22_begin(server, ns);
+retVal |= function_ua_namespace0_23_begin(server, ns);
+retVal |= function_ua_namespace0_24_begin(server, ns);
+retVal |= function_ua_namespace0_25_begin(server, ns);
+retVal |= function_ua_namespace0_26_begin(server, ns);
+retVal |= function_ua_namespace0_27_begin(server, ns);
+retVal |= function_ua_namespace0_28_begin(server, ns);
+retVal |= function_ua_namespace0_29_begin(server, ns);
+retVal |= function_ua_namespace0_30_begin(server, ns);
+retVal |= function_ua_namespace0_31_begin(server, ns);
+retVal |= function_ua_namespace0_32_begin(server, ns);
+retVal |= function_ua_namespace0_33_begin(server, ns);
+retVal |= function_ua_namespace0_34_begin(server, ns);
+retVal |= function_ua_namespace0_35_begin(server, ns);
+retVal |= function_ua_namespace0_36_begin(server, ns);
+retVal |= function_ua_namespace0_37_begin(server, ns);
+retVal |= function_ua_namespace0_38_begin(server, ns);
+retVal |= function_ua_namespace0_39_begin(server, ns);
+retVal |= function_ua_namespace0_40_begin(server, ns);
+retVal |= function_ua_namespace0_41_begin(server, ns);
+retVal |= function_ua_namespace0_42_begin(server, ns);
+retVal |= function_ua_namespace0_43_begin(server, ns);
+retVal |= function_ua_namespace0_44_begin(server, ns);
+retVal |= function_ua_namespace0_45_begin(server, ns);
+retVal |= function_ua_namespace0_46_begin(server, ns);
+retVal |= function_ua_namespace0_47_begin(server, ns);
+retVal |= function_ua_namespace0_48_begin(server, ns);
+retVal |= function_ua_namespace0_49_begin(server, ns);
+retVal |= function_ua_namespace0_50_begin(server, ns);
+retVal |= function_ua_namespace0_51_begin(server, ns);
+retVal |= function_ua_namespace0_52_begin(server, ns);
+retVal |= function_ua_namespace0_53_begin(server, ns);
+retVal |= function_ua_namespace0_54_begin(server, ns);
+retVal |= function_ua_namespace0_55_begin(server, ns);
+retVal |= function_ua_namespace0_56_begin(server, ns);
+retVal |= function_ua_namespace0_57_begin(server, ns);
+retVal |= function_ua_namespace0_58_begin(server, ns);
+retVal |= function_ua_namespace0_59_begin(server, ns);
+retVal |= function_ua_namespace0_60_begin(server, ns);
+retVal |= function_ua_namespace0_61_begin(server, ns);
+retVal |= function_ua_namespace0_62_begin(server, ns);
+retVal |= function_ua_namespace0_63_begin(server, ns);
+retVal |= function_ua_namespace0_64_begin(server, ns);
+retVal |= function_ua_namespace0_65_begin(server, ns);
+retVal |= function_ua_namespace0_66_begin(server, ns);
+retVal |= function_ua_namespace0_67_begin(server, ns);
+retVal |= function_ua_namespace0_68_begin(server, ns);
+retVal |= function_ua_namespace0_69_begin(server, ns);
+retVal |= function_ua_namespace0_70_begin(server, ns);
+retVal |= function_ua_namespace0_71_begin(server, ns);
+retVal |= function_ua_namespace0_72_begin(server, ns);
+retVal |= function_ua_namespace0_73_begin(server, ns);
+retVal |= function_ua_namespace0_74_begin(server, ns);
+retVal |= function_ua_namespace0_75_begin(server, ns);
+retVal |= function_ua_namespace0_76_begin(server, ns);
+retVal |= function_ua_namespace0_77_begin(server, ns);
+retVal |= function_ua_namespace0_78_begin(server, ns);
+retVal |= function_ua_namespace0_79_begin(server, ns);
+retVal |= function_ua_namespace0_80_begin(server, ns);
+retVal |= function_ua_namespace0_81_begin(server, ns);
+retVal |= function_ua_namespace0_82_begin(server, ns);
+retVal |= function_ua_namespace0_83_begin(server, ns);
+retVal |= function_ua_namespace0_84_begin(server, ns);
+retVal |= function_ua_namespace0_85_begin(server, ns);
+retVal |= function_ua_namespace0_86_begin(server, ns);
+retVal |= function_ua_namespace0_87_begin(server, ns);
+retVal |= function_ua_namespace0_88_begin(server, ns);
+retVal |= function_ua_namespace0_89_begin(server, ns);
+retVal |= function_ua_namespace0_90_begin(server, ns);
+retVal |= function_ua_namespace0_91_begin(server, ns);
+retVal |= function_ua_namespace0_92_begin(server, ns);
+retVal |= function_ua_namespace0_93_begin(server, ns);
+retVal |= function_ua_namespace0_94_begin(server, ns);
+retVal |= function_ua_namespace0_95_begin(server, ns);
+retVal |= function_ua_namespace0_96_begin(server, ns);
+retVal |= function_ua_namespace0_97_begin(server, ns);
+retVal |= function_ua_namespace0_98_begin(server, ns);
+retVal |= function_ua_namespace0_99_begin(server, ns);
+retVal |= function_ua_namespace0_100_begin(server, ns);
+retVal |= function_ua_namespace0_101_begin(server, ns);
+retVal |= function_ua_namespace0_102_begin(server, ns);
+retVal |= function_ua_namespace0_103_begin(server, ns);
+retVal |= function_ua_namespace0_104_begin(server, ns);
+retVal |= function_ua_namespace0_105_begin(server, ns);
+retVal |= function_ua_namespace0_106_begin(server, ns);
+retVal |= function_ua_namespace0_107_begin(server, ns);
+retVal |= function_ua_namespace0_108_begin(server, ns);
+retVal |= function_ua_namespace0_109_begin(server, ns);
+retVal |= function_ua_namespace0_110_begin(server, ns);
+retVal |= function_ua_namespace0_111_begin(server, ns);
+retVal |= function_ua_namespace0_112_begin(server, ns);
+retVal |= function_ua_namespace0_113_begin(server, ns);
+retVal |= function_ua_namespace0_114_begin(server, ns);
+retVal |= function_ua_namespace0_115_begin(server, ns);
+retVal |= function_ua_namespace0_116_begin(server, ns);
+retVal |= function_ua_namespace0_117_begin(server, ns);
+retVal |= function_ua_namespace0_118_begin(server, ns);
+retVal |= function_ua_namespace0_119_begin(server, ns);
+retVal |= function_ua_namespace0_120_begin(server, ns);
+retVal |= function_ua_namespace0_121_begin(server, ns);
+retVal |= function_ua_namespace0_122_begin(server, ns);
+retVal |= function_ua_namespace0_123_begin(server, ns);
+retVal |= function_ua_namespace0_124_begin(server, ns);
+retVal |= function_ua_namespace0_125_begin(server, ns);
+retVal |= function_ua_namespace0_126_begin(server, ns);
+retVal |= function_ua_namespace0_127_begin(server, ns);
+retVal |= function_ua_namespace0_128_begin(server, ns);
+retVal |= function_ua_namespace0_129_begin(server, ns);
+retVal |= function_ua_namespace0_130_begin(server, ns);
+retVal |= function_ua_namespace0_131_begin(server, ns);
+retVal |= function_ua_namespace0_132_begin(server, ns);
+retVal |= function_ua_namespace0_133_begin(server, ns);
+retVal |= function_ua_namespace0_133_finish(server, ns);
+retVal |= function_ua_namespace0_132_finish(server, ns);
+retVal |= function_ua_namespace0_131_finish(server, ns);
+retVal |= function_ua_namespace0_130_finish(server, ns);
+retVal |= function_ua_namespace0_129_finish(server, ns);
+retVal |= function_ua_namespace0_128_finish(server, ns);
+retVal |= function_ua_namespace0_127_finish(server, ns);
+retVal |= function_ua_namespace0_126_finish(server, ns);
+retVal |= function_ua_namespace0_125_finish(server, ns);
+retVal |= function_ua_namespace0_124_finish(server, ns);
+retVal |= function_ua_namespace0_123_finish(server, ns);
+retVal |= function_ua_namespace0_122_finish(server, ns);
+retVal |= function_ua_namespace0_121_finish(server, ns);
+retVal |= function_ua_namespace0_120_finish(server, ns);
+retVal |= function_ua_namespace0_119_finish(server, ns);
+retVal |= function_ua_namespace0_118_finish(server, ns);
+retVal |= function_ua_namespace0_117_finish(server, ns);
+retVal |= function_ua_namespace0_116_finish(server, ns);
+retVal |= function_ua_namespace0_115_finish(server, ns);
+retVal |= function_ua_namespace0_114_finish(server, ns);
+retVal |= function_ua_namespace0_113_finish(server, ns);
+retVal |= function_ua_namespace0_112_finish(server, ns);
+retVal |= function_ua_namespace0_111_finish(server, ns);
+retVal |= function_ua_namespace0_110_finish(server, ns);
+retVal |= function_ua_namespace0_109_finish(server, ns);
+retVal |= function_ua_namespace0_108_finish(server, ns);
+retVal |= function_ua_namespace0_107_finish(server, ns);
+retVal |= function_ua_namespace0_106_finish(server, ns);
+retVal |= function_ua_namespace0_105_finish(server, ns);
+retVal |= function_ua_namespace0_104_finish(server, ns);
+retVal |= function_ua_namespace0_103_finish(server, ns);
+retVal |= function_ua_namespace0_102_finish(server, ns);
+retVal |= function_ua_namespace0_101_finish(server, ns);
+retVal |= function_ua_namespace0_100_finish(server, ns);
+retVal |= function_ua_namespace0_99_finish(server, ns);
+retVal |= function_ua_namespace0_98_finish(server, ns);
+retVal |= function_ua_namespace0_97_finish(server, ns);
+retVal |= function_ua_namespace0_96_finish(server, ns);
+retVal |= function_ua_namespace0_95_finish(server, ns);
+retVal |= function_ua_namespace0_94_finish(server, ns);
+retVal |= function_ua_namespace0_93_finish(server, ns);
+retVal |= function_ua_namespace0_92_finish(server, ns);
+retVal |= function_ua_namespace0_91_finish(server, ns);
+retVal |= function_ua_namespace0_90_finish(server, ns);
+retVal |= function_ua_namespace0_89_finish(server, ns);
+retVal |= function_ua_namespace0_88_finish(server, ns);
+retVal |= function_ua_namespace0_87_finish(server, ns);
+retVal |= function_ua_namespace0_86_finish(server, ns);
+retVal |= function_ua_namespace0_85_finish(server, ns);
+retVal |= function_ua_namespace0_84_finish(server, ns);
+retVal |= function_ua_namespace0_83_finish(server, ns);
+retVal |= function_ua_namespace0_82_finish(server, ns);
+retVal |= function_ua_namespace0_81_finish(server, ns);
+retVal |= function_ua_namespace0_80_finish(server, ns);
+retVal |= function_ua_namespace0_79_finish(server, ns);
+retVal |= function_ua_namespace0_78_finish(server, ns);
+retVal |= function_ua_namespace0_77_finish(server, ns);
+retVal |= function_ua_namespace0_76_finish(server, ns);
+retVal |= function_ua_namespace0_75_finish(server, ns);
+retVal |= function_ua_namespace0_74_finish(server, ns);
+retVal |= function_ua_namespace0_73_finish(server, ns);
+retVal |= function_ua_namespace0_72_finish(server, ns);
+retVal |= function_ua_namespace0_71_finish(server, ns);
+retVal |= function_ua_namespace0_70_finish(server, ns);
+retVal |= function_ua_namespace0_69_finish(server, ns);
+retVal |= function_ua_namespace0_68_finish(server, ns);
+retVal |= function_ua_namespace0_67_finish(server, ns);
+retVal |= function_ua_namespace0_66_finish(server, ns);
+retVal |= function_ua_namespace0_65_finish(server, ns);
+retVal |= function_ua_namespace0_64_finish(server, ns);
+retVal |= function_ua_namespace0_63_finish(server, ns);
+retVal |= function_ua_namespace0_62_finish(server, ns);
+retVal |= function_ua_namespace0_61_finish(server, ns);
+retVal |= function_ua_namespace0_60_finish(server, ns);
+retVal |= function_ua_namespace0_59_finish(server, ns);
+retVal |= function_ua_namespace0_58_finish(server, ns);
+retVal |= function_ua_namespace0_57_finish(server, ns);
+retVal |= function_ua_namespace0_56_finish(server, ns);
+retVal |= function_ua_namespace0_55_finish(server, ns);
+retVal |= function_ua_namespace0_54_finish(server, ns);
+retVal |= function_ua_namespace0_53_finish(server, ns);
+retVal |= function_ua_namespace0_52_finish(server, ns);
+retVal |= function_ua_namespace0_51_finish(server, ns);
+retVal |= function_ua_namespace0_50_finish(server, ns);
+retVal |= function_ua_namespace0_49_finish(server, ns);
+retVal |= function_ua_namespace0_48_finish(server, ns);
+retVal |= function_ua_namespace0_47_finish(server, ns);
+retVal |= function_ua_namespace0_46_finish(server, ns);
+retVal |= function_ua_namespace0_45_finish(server, ns);
+retVal |= function_ua_namespace0_44_finish(server, ns);
+retVal |= function_ua_namespace0_43_finish(server, ns);
+retVal |= function_ua_namespace0_42_finish(server, ns);
+retVal |= function_ua_namespace0_41_finish(server, ns);
+retVal |= function_ua_namespace0_40_finish(server, ns);
+retVal |= function_ua_namespace0_39_finish(server, ns);
+retVal |= function_ua_namespace0_38_finish(server, ns);
+retVal |= function_ua_namespace0_37_finish(server, ns);
+retVal |= function_ua_namespace0_36_finish(server, ns);
+retVal |= function_ua_namespace0_35_finish(server, ns);
+retVal |= function_ua_namespace0_34_finish(server, ns);
+retVal |= function_ua_namespace0_33_finish(server, ns);
+retVal |= function_ua_namespace0_32_finish(server, ns);
+retVal |= function_ua_namespace0_31_finish(server, ns);
+retVal |= function_ua_namespace0_30_finish(server, ns);
+retVal |= function_ua_namespace0_29_finish(server, ns);
+retVal |= function_ua_namespace0_28_finish(server, ns);
+retVal |= function_ua_namespace0_27_finish(server, ns);
+retVal |= function_ua_namespace0_26_finish(server, ns);
+retVal |= function_ua_namespace0_25_finish(server, ns);
+retVal |= function_ua_namespace0_24_finish(server, ns);
+retVal |= function_ua_namespace0_23_finish(server, ns);
+retVal |= function_ua_namespace0_22_finish(server, ns);
+retVal |= function_ua_namespace0_21_finish(server, ns);
+retVal |= function_ua_namespace0_20_finish(server, ns);
+retVal |= function_ua_namespace0_19_finish(server, ns);
+retVal |= function_ua_namespace0_18_finish(server, ns);
+retVal |= function_ua_namespace0_17_finish(server, ns);
+retVal |= function_ua_namespace0_16_finish(server, ns);
+retVal |= function_ua_namespace0_15_finish(server, ns);
+retVal |= function_ua_namespace0_14_finish(server, ns);
+retVal |= function_ua_namespace0_13_finish(server, ns);
+retVal |= function_ua_namespace0_12_finish(server, ns);
+retVal |= function_ua_namespace0_11_finish(server, ns);
+retVal |= function_ua_namespace0_10_finish(server, ns);
+retVal |= function_ua_namespace0_9_finish(server, ns);
+retVal |= function_ua_namespace0_8_finish(server, ns);
+retVal |= function_ua_namespace0_7_finish(server, ns);
+retVal |= function_ua_namespace0_6_finish(server, ns);
+retVal |= function_ua_namespace0_5_finish(server, ns);
+retVal |= function_ua_namespace0_4_finish(server, ns);
+retVal |= function_ua_namespace0_3_finish(server, ns);
+retVal |= function_ua_namespace0_2_finish(server, ns);
+retVal |= function_ua_namespace0_1_finish(server, ns);
+retVal |= function_ua_namespace0_0_finish(server, ns);
+return retVal;
+}
+
+/*********************************** amalgamated original file "/home/jvoe/open62541/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-2017 (c) Julius Pfrommer, Fraunhofer IOSB
+ * Copyright 2014-2016 (c) Sten Grüner
+ * Copyright 2014-2015, 2017 (c) Florian Palm
+ * Copyright 2015-2016 (c) Chris Iatrou
+ * Copyright 2015-2016 (c) Oleksiy Vasylyev
+ * Copyright 2016 (c) Joakim L. Gilje
+ * Copyright 2016-2017 (c) Stefan Profanter, fortiss GmbH
+ * Copyright 2016 (c) TorbenD
+ * Copyright 2017 (c) frax2222
+ * Copyright 2017 (c) Mark Giraud, Fraunhofer IOSB
+ */
+
+
+#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
+// store the authentication token and session ID so we can help fuzzing by setting
+// these values in the next request automatically
+UA_NodeId unsafe_fuzz_authenticationToken = {
+ 0, UA_NODEIDTYPE_NUMERIC, {0}
+};
+#endif
+
+#ifdef UA_DEBUG_DUMP_PKGS_FILE
+void UA_debug_dumpCompleteChunk(UA_Server *const server, UA_Connection *const connection, UA_ByteString *messageBuffer);
+#endif
+
+/********************/
+/* Helper Functions */
+/********************/
+
+ /* This is not an ERR message, the connection is not closed afterwards */
+static UA_StatusCode
+sendServiceFault(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);
+ if(retval != UA_STATUSCODE_GOOD)
+ return retval;
+ UA_STACKARRAY(UA_Byte, response, responseType->memSize);
+ UA_init(response, responseType);
+ UA_ResponseHeader *responseHeader = (UA_ResponseHeader*)response;
+ responseHeader->requestHandle = requestHeader.requestHandle;
+ responseHeader->timestamp = UA_DateTime_now();
+ responseHeader->serviceResult = error;
+
+ // Send error message. Message type is MSG and not ERR, since we are on a securechannel!
+ retval = UA_SecureChannel_sendSymmetricMessage(channel, requestId, UA_MESSAGETYPE_MSG,
+ response, responseType);
+
+ UA_RequestHeader_deleteMembers(&requestHeader);
+ UA_LOG_DEBUG(channel->securityPolicy->logger, UA_LOGCATEGORY_SERVER,
+ "Sent ServiceFault with error code %s", UA_StatusCode_name(error));
+ return retval;
+}
+
+typedef enum {
+ UA_SERVICETYPE_NORMAL,
+ UA_SERVICETYPE_INSITU,
+ UA_SERVICETYPE_CUSTOM
+} UA_ServiceType;
+
+static void
+getServicePointers(UA_UInt32 requestTypeId, const UA_DataType **requestType,
+ const UA_DataType **responseType, UA_Service *service,
+ UA_InSituService *serviceInsitu,
+ UA_Boolean *requiresSession, UA_ServiceType *serviceType) {
+ switch(requestTypeId) {
+ case UA_NS0ID_GETENDPOINTSREQUEST_ENCODING_DEFAULTBINARY:
+ *service = (UA_Service)Service_GetEndpoints;
+ *requestType = &UA_TYPES[UA_TYPES_GETENDPOINTSREQUEST];
+ *responseType = &UA_TYPES[UA_TYPES_GETENDPOINTSRESPONSE];
+ *requiresSession = false;
+ break;
+ case UA_NS0ID_FINDSERVERSREQUEST_ENCODING_DEFAULTBINARY:
+ *service = (UA_Service)Service_FindServers;
+ *requestType = &UA_TYPES[UA_TYPES_FINDSERVERSREQUEST];
+ *responseType = &UA_TYPES[UA_TYPES_FINDSERVERSRESPONSE];
+ *requiresSession = false;
+ break;
+#ifdef UA_ENABLE_DISCOVERY
+# ifdef UA_ENABLE_DISCOVERY_MULTICAST
+ case UA_NS0ID_FINDSERVERSONNETWORKREQUEST_ENCODING_DEFAULTBINARY:
+ *service = (UA_Service)Service_FindServersOnNetwork;
+ *requestType = &UA_TYPES[UA_TYPES_FINDSERVERSONNETWORKREQUEST];
+ *responseType = &UA_TYPES[UA_TYPES_FINDSERVERSONNETWORKRESPONSE];
+ *requiresSession = false;
+ break;
+# endif
+ case UA_NS0ID_REGISTERSERVERREQUEST_ENCODING_DEFAULTBINARY:
+ *service = (UA_Service)Service_RegisterServer;
+ *requestType = &UA_TYPES[UA_TYPES_REGISTERSERVERREQUEST];
+ *responseType = &UA_TYPES[UA_TYPES_REGISTERSERVERRESPONSE];
+ *requiresSession = false;
+ break;
+ case UA_NS0ID_REGISTERSERVER2REQUEST_ENCODING_DEFAULTBINARY:
+ *service = (UA_Service)Service_RegisterServer2;
+ *requestType = &UA_TYPES[UA_TYPES_REGISTERSERVER2REQUEST];
+ *responseType = &UA_TYPES[UA_TYPES_REGISTERSERVER2RESPONSE];
+ *requiresSession = false;
+ break;
+#endif
+ case UA_NS0ID_CREATESESSIONREQUEST_ENCODING_DEFAULTBINARY:
+ *service = NULL; //(UA_Service)Service_CreateSession;
+ *requestType = &UA_TYPES[UA_TYPES_CREATESESSIONREQUEST];
+ *responseType = &UA_TYPES[UA_TYPES_CREATESESSIONRESPONSE];
+ *requiresSession = false;
+ *serviceType = UA_SERVICETYPE_CUSTOM;
+ break;
+ case UA_NS0ID_ACTIVATESESSIONREQUEST_ENCODING_DEFAULTBINARY:
+ *service = NULL; //(UA_Service)Service_ActivateSession;
+ *requestType = &UA_TYPES[UA_TYPES_ACTIVATESESSIONREQUEST];
+ *responseType = &UA_TYPES[UA_TYPES_ACTIVATESESSIONRESPONSE];
+ *serviceType = UA_SERVICETYPE_CUSTOM;
+ break;
+ case UA_NS0ID_CLOSESESSIONREQUEST_ENCODING_DEFAULTBINARY:
+ *service = (UA_Service)Service_CloseSession;
+ *requestType = &UA_TYPES[UA_TYPES_CLOSESESSIONREQUEST];
+ *responseType = &UA_TYPES[UA_TYPES_CLOSESESSIONRESPONSE];
+ break;
+ case UA_NS0ID_READREQUEST_ENCODING_DEFAULTBINARY:
+ *service = NULL;
+ *serviceInsitu = (UA_InSituService)Service_Read;
+ *requestType = &UA_TYPES[UA_TYPES_READREQUEST];
+ *responseType = &UA_TYPES[UA_TYPES_READRESPONSE];
+ *serviceType = UA_SERVICETYPE_INSITU;
+ break;
+ case UA_NS0ID_WRITEREQUEST_ENCODING_DEFAULTBINARY:
+ *service = (UA_Service)Service_Write;
+ *requestType = &UA_TYPES[UA_TYPES_WRITEREQUEST];
+ *responseType = &UA_TYPES[UA_TYPES_WRITERESPONSE];
+ break;
+ case UA_NS0ID_BROWSEREQUEST_ENCODING_DEFAULTBINARY:
+ *service = (UA_Service)Service_Browse;
+ *requestType = &UA_TYPES[UA_TYPES_BROWSEREQUEST];
+ *responseType = &UA_TYPES[UA_TYPES_BROWSERESPONSE];
+ break;
+ case UA_NS0ID_BROWSENEXTREQUEST_ENCODING_DEFAULTBINARY:
+ *service = (UA_Service)Service_BrowseNext;
+ *requestType = &UA_TYPES[UA_TYPES_BROWSENEXTREQUEST];
+ *responseType = &UA_TYPES[UA_TYPES_BROWSENEXTRESPONSE];
+ break;
+ case UA_NS0ID_REGISTERNODESREQUEST_ENCODING_DEFAULTBINARY:
+ *service = (UA_Service)Service_RegisterNodes;
+ *requestType = &UA_TYPES[UA_TYPES_REGISTERNODESREQUEST];
+ *responseType = &UA_TYPES[UA_TYPES_REGISTERNODESRESPONSE];
+ break;
+ case UA_NS0ID_UNREGISTERNODESREQUEST_ENCODING_DEFAULTBINARY:
+ *service = (UA_Service)Service_UnregisterNodes;
+ *requestType = &UA_TYPES[UA_TYPES_UNREGISTERNODESREQUEST];
+ *responseType = &UA_TYPES[UA_TYPES_UNREGISTERNODESRESPONSE];
+ break;
+ case UA_NS0ID_TRANSLATEBROWSEPATHSTONODEIDSREQUEST_ENCODING_DEFAULTBINARY:
+ *service = (UA_Service)Service_TranslateBrowsePathsToNodeIds;
+ *requestType = &UA_TYPES[UA_TYPES_TRANSLATEBROWSEPATHSTONODEIDSREQUEST];
+ *responseType = &UA_TYPES[UA_TYPES_TRANSLATEBROWSEPATHSTONODEIDSRESPONSE];
+ break;
+
+#ifdef UA_ENABLE_SUBSCRIPTIONS
+ case UA_NS0ID_CREATESUBSCRIPTIONREQUEST_ENCODING_DEFAULTBINARY:
+ *service = (UA_Service)Service_CreateSubscription;
+ *requestType = &UA_TYPES[UA_TYPES_CREATESUBSCRIPTIONREQUEST];
+ *responseType = &UA_TYPES[UA_TYPES_CREATESUBSCRIPTIONRESPONSE];
+ break;
+ case UA_NS0ID_PUBLISHREQUEST_ENCODING_DEFAULTBINARY:
+ *requestType = &UA_TYPES[UA_TYPES_PUBLISHREQUEST];
+ *responseType = &UA_TYPES[UA_TYPES_PUBLISHRESPONSE];
+ break;
+ case UA_NS0ID_REPUBLISHREQUEST_ENCODING_DEFAULTBINARY:
+ *service = (UA_Service)Service_Republish;
+ *requestType = &UA_TYPES[UA_TYPES_REPUBLISHREQUEST];
+ *responseType = &UA_TYPES[UA_TYPES_REPUBLISHRESPONSE];
+ break;
+ case UA_NS0ID_MODIFYSUBSCRIPTIONREQUEST_ENCODING_DEFAULTBINARY:
+ *service = (UA_Service)Service_ModifySubscription;
+ *requestType = &UA_TYPES[UA_TYPES_MODIFYSUBSCRIPTIONREQUEST];
+ *responseType = &UA_TYPES[UA_TYPES_MODIFYSUBSCRIPTIONRESPONSE];
+ break;
+ case UA_NS0ID_SETPUBLISHINGMODEREQUEST_ENCODING_DEFAULTBINARY:
+ *service = (UA_Service)Service_SetPublishingMode;
+ *requestType = &UA_TYPES[UA_TYPES_SETPUBLISHINGMODEREQUEST];
+ *responseType = &UA_TYPES[UA_TYPES_SETPUBLISHINGMODERESPONSE];
+ break;
+ case UA_NS0ID_DELETESUBSCRIPTIONSREQUEST_ENCODING_DEFAULTBINARY:
+ *service = (UA_Service)Service_DeleteSubscriptions;
+ *requestType = &UA_TYPES[UA_TYPES_DELETESUBSCRIPTIONSREQUEST];
+ *responseType = &UA_TYPES[UA_TYPES_DELETESUBSCRIPTIONSRESPONSE];
+ break;
+ case UA_NS0ID_CREATEMONITOREDITEMSREQUEST_ENCODING_DEFAULTBINARY:
+ *service = (UA_Service)Service_CreateMonitoredItems;
+ *requestType = &UA_TYPES[UA_TYPES_CREATEMONITOREDITEMSREQUEST];
+ *responseType = &UA_TYPES[UA_TYPES_CREATEMONITOREDITEMSRESPONSE];
+ break;
+ case UA_NS0ID_DELETEMONITOREDITEMSREQUEST_ENCODING_DEFAULTBINARY:
+ *service = (UA_Service)Service_DeleteMonitoredItems;
+ *requestType = &UA_TYPES[UA_TYPES_DELETEMONITOREDITEMSREQUEST];
+ *responseType = &UA_TYPES[UA_TYPES_DELETEMONITOREDITEMSRESPONSE];
+ break;
+ case UA_NS0ID_MODIFYMONITOREDITEMSREQUEST_ENCODING_DEFAULTBINARY:
+ *service = (UA_Service)Service_ModifyMonitoredItems;
+ *requestType = &UA_TYPES[UA_TYPES_MODIFYMONITOREDITEMSREQUEST];
+ *responseType = &UA_TYPES[UA_TYPES_MODIFYMONITOREDITEMSRESPONSE];
+ break;
+ case UA_NS0ID_SETMONITORINGMODEREQUEST_ENCODING_DEFAULTBINARY:
+ *service = (UA_Service)Service_SetMonitoringMode;
+ *requestType = &UA_TYPES[UA_TYPES_SETMONITORINGMODEREQUEST];
+ *responseType = &UA_TYPES[UA_TYPES_SETMONITORINGMODERESPONSE];
+ break;
+#endif
+
+#ifdef UA_ENABLE_METHODCALLS
+ case UA_NS0ID_CALLREQUEST_ENCODING_DEFAULTBINARY:
+ *service = (UA_Service)Service_Call;
+ *requestType = &UA_TYPES[UA_TYPES_CALLREQUEST];
+ *responseType = &UA_TYPES[UA_TYPES_CALLRESPONSE];
+ break;
+#endif
+
+#ifdef UA_ENABLE_NODEMANAGEMENT
+ case UA_NS0ID_ADDNODESREQUEST_ENCODING_DEFAULTBINARY:
+ *service = (UA_Service)Service_AddNodes;
+ *requestType = &UA_TYPES[UA_TYPES_ADDNODESREQUEST];
+ *responseType = &UA_TYPES[UA_TYPES_ADDNODESRESPONSE];
+ break;
+ case UA_NS0ID_ADDREFERENCESREQUEST_ENCODING_DEFAULTBINARY:
+ *service = (UA_Service)Service_AddReferences;
+ *requestType = &UA_TYPES[UA_TYPES_ADDREFERENCESREQUEST];
+ *responseType = &UA_TYPES[UA_TYPES_ADDREFERENCESRESPONSE];
+ break;
+ case UA_NS0ID_DELETENODESREQUEST_ENCODING_DEFAULTBINARY:
+ *service = (UA_Service)Service_DeleteNodes;
+ *requestType = &UA_TYPES[UA_TYPES_DELETENODESREQUEST];
+ *responseType = &UA_TYPES[UA_TYPES_DELETENODESRESPONSE];
+ break;
+ case UA_NS0ID_DELETEREFERENCESREQUEST_ENCODING_DEFAULTBINARY:
+ *service = (UA_Service)Service_DeleteReferences;
+ *requestType = &UA_TYPES[UA_TYPES_DELETEREFERENCESREQUEST];
+ *responseType = &UA_TYPES[UA_TYPES_DELETEREFERENCESRESPONSE];
+ break;
+#endif
+
+ default:
+ break;
+ }
+}
+
+/*************************/
+/* Process Message Types */
+/*************************/
+
+/* HEL -> Open up the connection */
+static UA_StatusCode
+processHEL(UA_Server *server, UA_Connection *connection,
+ const UA_ByteString *msg, size_t *offset) {
+ UA_TcpHelloMessage helloMessage;
+ UA_StatusCode retval = UA_TcpHelloMessage_decodeBinary(msg, offset, &helloMessage);
+ if(retval != UA_STATUSCODE_GOOD)
+ return retval;
+
+ /* Parameterize the connection */
+ connection->remoteConf.maxChunkCount = helloMessage.maxChunkCount; /* zero -> unlimited */
+ connection->remoteConf.maxMessageSize = helloMessage.maxMessageSize; /* zero -> unlimited */
+ connection->remoteConf.protocolVersion = helloMessage.protocolVersion;
+ connection->remoteConf.recvBufferSize = helloMessage.receiveBufferSize;
+ if(connection->localConf.sendBufferSize > helloMessage.receiveBufferSize)
+ connection->localConf.sendBufferSize = helloMessage.receiveBufferSize;
+ connection->remoteConf.sendBufferSize = helloMessage.sendBufferSize;
+ if(connection->localConf.recvBufferSize > helloMessage.sendBufferSize)
+ connection->localConf.recvBufferSize = helloMessage.sendBufferSize;
+ UA_String_deleteMembers(&helloMessage.endpointUrl);
+
+ if(connection->remoteConf.recvBufferSize == 0) {
+ UA_LOG_INFO(server->config.logger, UA_LOGCATEGORY_NETWORK,
+ "Connection %i | Remote end indicated a receive buffer size of 0. "
+ "Not able to send any messages.",
+ connection->sockfd);
+ return UA_STATUSCODE_BADINTERNALERROR;
+ }
+
+ connection->state = UA_CONNECTION_ESTABLISHED;
+
+ /* Build acknowledge response */
+ UA_TcpAcknowledgeMessage ackMessage;
+ ackMessage.protocolVersion = connection->localConf.protocolVersion;
+ ackMessage.receiveBufferSize = connection->localConf.recvBufferSize;
+ ackMessage.sendBufferSize = connection->localConf.sendBufferSize;
+ ackMessage.maxMessageSize = connection->localConf.maxMessageSize;
+ ackMessage.maxChunkCount = connection->localConf.maxChunkCount;
+ UA_TcpMessageHeader ackHeader;
+ ackHeader.messageTypeAndChunkType = UA_MESSAGETYPE_ACK + UA_CHUNKTYPE_FINAL;
+ ackHeader.messageSize = 8 + 20; /* ackHeader + ackMessage */
+
+ /* Get the send buffer from the network layer */
+ UA_ByteString ack_msg;
+ UA_ByteString_init(&ack_msg);
+ retval = connection->getSendBuffer(connection, connection->localConf.sendBufferSize,
+ &ack_msg);
+ if(retval != UA_STATUSCODE_GOOD)
+ return retval;
+
+ /* 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);
+ if(retval != UA_STATUSCODE_GOOD) {
+ connection->releaseSendBuffer(connection, &ack_msg);
+ return retval;
+ }
+
+ retval = UA_TcpAcknowledgeMessage_encodeBinary(&ackMessage, &bufPos, &bufEnd);
+ if(retval != UA_STATUSCODE_GOOD) {
+ connection->releaseSendBuffer(connection, &ack_msg);
+ return retval;
+ }
+ ack_msg.length = ackHeader.messageSize;
+ return connection->send(connection, &ack_msg);
+}
+
+/* OPN -> Open up/renew the securechannel */
+static UA_StatusCode
+processOPN(UA_Server *server, UA_SecureChannel *channel,
+ const UA_UInt32 requestId, const UA_ByteString *msg) {
+ /* Decode the request */
+ size_t offset = 0;
+ UA_NodeId requestType;
+ UA_StatusCode retval = UA_STATUSCODE_GOOD;
+ UA_OpenSecureChannelRequest openSecureChannelRequest;
+ retval |= UA_NodeId_decodeBinary(msg, &offset, &requestType);
+ retval |= UA_OpenSecureChannelRequest_decodeBinary(msg, &offset, &openSecureChannelRequest);
+
+ /* Error occurred */
+ if(retval != UA_STATUSCODE_GOOD ||
+ requestType.identifier.numeric != UA_TYPES[UA_TYPES_OPENSECURECHANNELREQUEST].binaryEncodingId) {
+ UA_NodeId_deleteMembers(&requestType);
+ UA_OpenSecureChannelRequest_deleteMembers(&openSecureChannelRequest);
+ UA_LOG_INFO_CHANNEL(server->config.logger, channel,
+ "Could not decode the OPN message. Closing the connection.");
+ UA_SecureChannelManager_close(&server->secureChannelManager, channel->securityToken.channelId);
+ return retval;
+ }
+ UA_NodeId_deleteMembers(&requestType);
+
+ /* Call the service */
+ UA_OpenSecureChannelResponse openScResponse;
+ UA_OpenSecureChannelResponse_init(&openScResponse);
+ Service_OpenSecureChannel(server, channel, &openSecureChannelRequest, &openScResponse);
+ UA_OpenSecureChannelRequest_deleteMembers(&openSecureChannelRequest);
+ if(openScResponse.responseHeader.serviceResult != UA_STATUSCODE_GOOD) {
+ UA_LOG_INFO_CHANNEL(server->config.logger, channel, "Could not open a SecureChannel. "
+ "Closing the connection.");
+ UA_SecureChannelManager_close(&server->secureChannelManager,
+ channel->securityToken.channelId);
+ return openScResponse.responseHeader.serviceResult;
+ }
+
+ /* Send the response */
+ retval = UA_SecureChannel_sendAsymmetricOPNMessage(channel, requestId, &openScResponse,
+ &UA_TYPES[UA_TYPES_OPENSECURECHANNELRESPONSE]);
+ UA_OpenSecureChannelResponse_deleteMembers(&openScResponse);
+ if(retval != UA_STATUSCODE_GOOD) {
+ UA_LOG_INFO_CHANNEL(server->config.logger, channel,
+ "Could not send the OPN answer with error code %s",
+ UA_StatusCode_name(retval));
+ UA_SecureChannelManager_close(&server->secureChannelManager,
+ channel->securityToken.channelId);
+ }
+ return retval;
+}
+
+static UA_StatusCode
+processMSG(UA_Server *server, UA_SecureChannel *channel,
+ UA_UInt32 requestId, const UA_ByteString *msg) {
+ /* At 0, the nodeid starts... */
+ size_t offset = 0;
+
+ /* Decode the nodeid */
+ UA_NodeId requestTypeId;
+ UA_StatusCode retval = UA_NodeId_decodeBinary(msg, &offset, &requestTypeId);
+ if(retval != UA_STATUSCODE_GOOD)
+ return retval;
+ if(requestTypeId.namespaceIndex != 0 ||
+ requestTypeId.identifierType != UA_NODEIDTYPE_NUMERIC)
+ UA_NodeId_deleteMembers(&requestTypeId); /* leads to badserviceunsupported */
+
+ /* Store the start-position of the request */
+ size_t requestPos = offset;
+
+ /* Get the service pointers */
+ UA_Service service = NULL;
+ UA_InSituService serviceInsitu = NULL;
+ const UA_DataType *requestType = NULL;
+ const UA_DataType *responseType = NULL;
+ UA_Boolean sessionRequired = true;
+ UA_ServiceType serviceType = UA_SERVICETYPE_NORMAL;
+ getServicePointers(requestTypeId.identifier.numeric, &requestType,
+ &responseType, &service, &serviceInsitu, &sessionRequired, &serviceType);
+ if(!requestType) {
+ if(requestTypeId.identifier.numeric == 787) {
+ UA_LOG_INFO_CHANNEL(server->config.logger, channel,
+ "Client requested a subscription, " \
+ "but those are not enabled in the build");
+ } else {
+ UA_LOG_INFO_CHANNEL(server->config.logger, channel,
+ "Unknown request with type identifier %i",
+ requestTypeId.identifier.numeric);
+ }
+ return sendServiceFault(channel, msg, requestPos, &UA_TYPES[UA_TYPES_SERVICEFAULT],
+ requestId, UA_STATUSCODE_BADSERVICEUNSUPPORTED);
+ }
+ UA_assert(responseType);
+
+ /* Decode the request */
+ UA_STACKARRAY(UA_Byte, request, requestType->memSize);
+ UA_RequestHeader *requestHeader = (UA_RequestHeader*)request;
+ retval = UA_decodeBinary(msg, &offset, request, requestType,
+ server->config.customDataTypesSize,
+ server->config.customDataTypes);
+ if(retval != UA_STATUSCODE_GOOD) {
+ UA_LOG_DEBUG_CHANNEL(server->config.logger, channel,
+ "Could not decode the request");
+ return sendServiceFault(channel, msg, requestPos, responseType, requestId, retval);
+ }
+
+ /* Prepare the respone */
+ UA_STACKARRAY(UA_Byte, responseBuf, responseType->memSize);
+ void *response = (void*)(uintptr_t)&responseBuf[0]; /* Get around aliasing rules */
+ UA_init(response, responseType);
+ UA_Session *session = NULL; /* must be initialized before goto send_response */
+
+ /* CreateSession doesn't need a session */
+ if(requestType == &UA_TYPES[UA_TYPES_CREATESESSIONREQUEST]) {
+ Service_CreateSession(server, channel,
+ (const UA_CreateSessionRequest *)request,
+ (UA_CreateSessionResponse *)response);
+ #ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
+ // store the authentication token and session ID so we can help fuzzing by setting
+ // these values in the next request automatically
+ UA_CreateSessionResponse *res = (UA_CreateSessionResponse *)response;
+ UA_NodeId_copy(&res->authenticationToken, &unsafe_fuzz_authenticationToken);
+ #endif
+ goto send_response;
+ }
+
+ #ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
+ // set the authenticationToken from the create session request to help fuzzing cover more lines
+ UA_NodeId_deleteMembers(&requestHeader->authenticationToken);
+ if(!UA_NodeId_isNull(&unsafe_fuzz_authenticationToken))
+ UA_NodeId_copy(&unsafe_fuzz_authenticationToken, &requestHeader->authenticationToken);
+ #endif
+
+ /* Find the matching session */
+ session = (UA_Session*)UA_SecureChannel_getSession(channel, &requestHeader->authenticationToken);
+ if(!session && !UA_NodeId_isNull(&requestHeader->authenticationToken))
+ session = UA_SessionManager_getSessionByToken(&server->sessionManager,
+ &requestHeader->authenticationToken);
+
+ if(requestType == &UA_TYPES[UA_TYPES_ACTIVATESESSIONREQUEST]) {
+ if(!session) {
+ UA_LOG_DEBUG_CHANNEL(server->config.logger, channel,
+ "Trying to activate a session that is " \
+ "not known in the server");
+ UA_deleteMembers(request, requestType);
+ return sendServiceFault(channel, msg, requestPos, responseType,
+ requestId, UA_STATUSCODE_BADSESSIONIDINVALID);
+ }
+ Service_ActivateSession(server, channel, session,
+ (const UA_ActivateSessionRequest*)request,
+ (UA_ActivateSessionResponse*)response);
+ goto send_response;
+ }
+
+ /* Set an anonymous, inactive session for services that need no session */
+ UA_Session anonymousSession;
+ if(!session) {
+ if(sessionRequired) {
+ UA_LOG_WARNING_CHANNEL(server->config.logger, channel,
+ "Service request %i without a valid session",
+ requestType->binaryEncodingId);
+ UA_deleteMembers(request, requestType);
+ return sendServiceFault(channel, msg, requestPos, responseType,
+ requestId, UA_STATUSCODE_BADSESSIONIDINVALID);
+ }
+
+ UA_Session_init(&anonymousSession);
+ anonymousSession.sessionId = UA_NODEID_GUID(0, UA_GUID_NULL);
+ anonymousSession.header.channel = channel;
+ session = &anonymousSession;
+ }
+
+ /* Trying to use a non-activated session? */
+ if(sessionRequired && !session->activated) {
+ UA_LOG_WARNING_SESSION(server->config.logger, session,
+ "Calling service %i on a non-activated session",
+ requestType->binaryEncodingId);
+ UA_SessionManager_removeSession(&server->sessionManager,
+ &session->header.authenticationToken);
+ UA_deleteMembers(request, requestType);
+ return sendServiceFault(channel, msg, requestPos, responseType,
+ requestId, UA_STATUSCODE_BADSESSIONNOTACTIVATED);
+ }
+
+ /* The session is bound to another channel */
+ if(session != &anonymousSession && session->header.channel != channel) {
+ UA_LOG_WARNING_CHANNEL(server->config.logger, channel,
+ "Client tries to use a Session that is not "
+ "bound to this SecureChannel");
+ UA_deleteMembers(request, requestType);
+ return sendServiceFault(channel, msg, requestPos, responseType,
+ requestId, UA_STATUSCODE_BADSECURECHANNELIDINVALID);
+ }
+
+ /* Update the session lifetime */
+ UA_Session_updateLifetime(session);
+
+#ifdef UA_ENABLE_SUBSCRIPTIONS
+ /* The publish request is not answered immediately */
+ if(requestType == &UA_TYPES[UA_TYPES_PUBLISHREQUEST]) {
+ Service_Publish(server, session,
+ (const UA_PublishRequest*)request, requestId);
+ UA_deleteMembers(request, requestType);
+ return UA_STATUSCODE_GOOD;
+ }
+#endif
+
+ send_response:
+
+ /* Prepare the ResponseHeader */
+ ((UA_ResponseHeader*)response)->requestHandle = requestHeader->requestHandle;
+ ((UA_ResponseHeader*)response)->timestamp = UA_DateTime_now();
+
+ /* Process normal services before initializing the message context.
+ * Some services may initialize new message contexts and to support network
+ * layers only providing one send buffer, only one message context can be
+ * initialized concurrently. */
+ if(serviceType == UA_SERVICETYPE_NORMAL)
+ service(server, session, request, response);
+
+ /* Start the message */
+ UA_NodeId typeId = UA_NODEID_NUMERIC(0, responseType->binaryEncodingId);
+ UA_MessageContext mc;
+ retval = UA_MessageContext_begin(&mc, channel, requestId, UA_MESSAGETYPE_MSG);
+ if(retval != UA_STATUSCODE_GOOD)
+ goto cleanup;
+
+ /* Assert's required for clang-analyzer */
+ UA_assert(mc.buf_pos == &mc.messageBuffer.data[UA_SECURE_MESSAGE_HEADER_LENGTH]);
+ UA_assert(mc.buf_end <= &mc.messageBuffer.data[mc.messageBuffer.length]);
+
+ retval = UA_MessageContext_encode(&mc, &typeId, &UA_TYPES[UA_TYPES_NODEID]);
+ if(retval != UA_STATUSCODE_GOOD)
+ goto cleanup;
+
+ switch(serviceType) {
+ case UA_SERVICETYPE_CUSTOM:
+ /* Was processed before...*/
+ retval = UA_MessageContext_encode(&mc, response, responseType);
+ break;
+ case UA_SERVICETYPE_INSITU:
+ retval = serviceInsitu
+ (server, session, &mc, request, (UA_ResponseHeader*)response);
+ break;
+ case UA_SERVICETYPE_NORMAL:
+ default:
+ retval = UA_MessageContext_encode(&mc, response, responseType);
+ break;
+ }
+
+ /* Finish sending the message */
+ if(retval != UA_STATUSCODE_GOOD) {
+ UA_MessageContext_abort(&mc);
+ goto cleanup;
+ }
+
+ retval = UA_MessageContext_finish(&mc);
+
+ cleanup:
+ if(retval != UA_STATUSCODE_GOOD)
+ UA_LOG_INFO_CHANNEL(server->config.logger, channel,
+ "Could not send the message over the SecureChannel "
+ "with StatusCode %s", UA_StatusCode_name(retval));
+ /* Clean up */
+ UA_deleteMembers(request, requestType);
+ UA_deleteMembers(response, responseType);
+ return retval;
+}
+
+/* Takes decoded messages starting at the nodeid of the content type. */
+static UA_StatusCode
+processSecureChannelMessage(void *application, UA_SecureChannel *channel,
+ UA_MessageType messagetype, UA_UInt32 requestId,
+ const UA_ByteString *message) {
+ UA_Server *server = (UA_Server*)application;
+ UA_StatusCode retval = UA_STATUSCODE_GOOD;
+ switch(messagetype) {
+ case UA_MESSAGETYPE_OPN:
+ UA_LOG_TRACE_CHANNEL(server->config.logger, channel,
+ "Process an OPN on an open channel");
+ retval = processOPN(server, channel, requestId, message);
+ break;
+ case UA_MESSAGETYPE_MSG:
+ UA_LOG_TRACE_CHANNEL(server->config.logger, channel, "Process a MSG");
+ retval = processMSG(server, channel, requestId, message);
+ break;
+ case UA_MESSAGETYPE_CLO:
+ UA_LOG_TRACE_CHANNEL(server->config.logger, channel, "Process a CLO");
+ Service_CloseSecureChannel(server, channel);
+ break;
+ default:
+ UA_LOG_TRACE_CHANNEL(server->config.logger, channel, "Invalid message type");
+ retval = UA_STATUSCODE_BADTCPMESSAGETYPEINVALID;
+ break;
+ }
+ return retval;
+}
+
+static UA_StatusCode
+createSecureChannel(void *application, UA_Connection *connection,
+ UA_AsymmetricAlgorithmSecurityHeader *asymHeader) {
+ UA_Server *server = (UA_Server*)application;
+
+ /* Iterate over available endpoints and choose the correct one */
+ UA_Endpoint *endpoint = NULL;
+ UA_StatusCode retval = UA_STATUSCODE_GOOD;
+ for(size_t i = 0; i < server->config.endpointsSize; ++i) {
+ UA_Endpoint *endpointCandidate = &server->config.endpoints[i];
+ if(!UA_ByteString_equal(&asymHeader->securityPolicyUri,
+ &endpointCandidate->securityPolicy.policyUri))
+ continue;
+ retval = endpointCandidate->securityPolicy.asymmetricModule.
+ compareCertificateThumbprint(&endpointCandidate->securityPolicy,
+ &asymHeader->receiverCertificateThumbprint);
+ if(retval != UA_STATUSCODE_GOOD)
+ continue;
+
+ /* We found the correct endpoint (except for security mode) The endpoint
+ * needs to be changed by the client / server to match the security
+ * mode. The server does this in the securechannel manager */
+ endpoint = endpointCandidate;
+ break;
+ }
+
+ if(!endpoint)
+ return UA_STATUSCODE_BADSECURITYPOLICYREJECTED;
+
+ /* Create a new channel */
+ return UA_SecureChannelManager_create(&server->secureChannelManager, connection,
+ &endpoint->securityPolicy, asymHeader);
+}
+
+static UA_StatusCode
+processCompleteChunkWithoutChannel(UA_Server *server, UA_Connection *connection,
+ UA_ByteString *message) {
+ /* Process chunk without a channel; must be OPN */
+ UA_LOG_TRACE(server->config.logger, UA_LOGCATEGORY_NETWORK,
+ "Connection %i | No channel attached to the connection. "
+ "Process the chunk directly", connection->sockfd);
+ size_t offset = 0;
+ UA_TcpMessageHeader tcpMessageHeader;
+ UA_StatusCode retval =
+ UA_TcpMessageHeader_decodeBinary(message, &offset, &tcpMessageHeader);
+ if(retval != UA_STATUSCODE_GOOD)
+ return retval;
+
+ // Only HEL and OPN messages possible without a channel (on the server side)
+ switch(tcpMessageHeader.messageTypeAndChunkType & 0x00ffffff) {
+ case UA_MESSAGETYPE_HEL:
+ retval = processHEL(server, connection, message, &offset);
+ break;
+ case UA_MESSAGETYPE_OPN:
+ {
+ UA_LOG_TRACE(server->config.logger, UA_LOGCATEGORY_NETWORK,
+ "Connection %i | Process OPN message", connection->sockfd);
+
+ /* Called before HEL */
+ if(connection->state != UA_CONNECTION_ESTABLISHED) {
+ retval = UA_STATUSCODE_BADCOMMUNICATIONERROR;
+ break;
+ }
+
+ // Decode the asymmetric algorithm security header since it is not encrypted and
+ // needed to decide what security policy to use.
+ UA_AsymmetricAlgorithmSecurityHeader asymHeader;
+ UA_AsymmetricAlgorithmSecurityHeader_init(&asymHeader);
+ size_t messageHeaderOffset = UA_SECURE_CONVERSATION_MESSAGE_HEADER_LENGTH;
+ retval = UA_AsymmetricAlgorithmSecurityHeader_decodeBinary(message,
+ &messageHeaderOffset,
+ &asymHeader);
+ if(retval != UA_STATUSCODE_GOOD)
+ break;
+
+ retval = createSecureChannel(server, connection, &asymHeader);
+ UA_AsymmetricAlgorithmSecurityHeader_deleteMembers(&asymHeader);
+ if(retval != UA_STATUSCODE_GOOD)
+ break;
+
+ retval = UA_SecureChannel_processChunk(connection->channel, message,
+ processSecureChannelMessage,
+ server, UA_FALSE);
+ if(retval != UA_STATUSCODE_GOOD)
+ break;
+ break;
+ }
+ default:
+ UA_LOG_TRACE(server->config.logger, UA_LOGCATEGORY_NETWORK,
+ "Connection %i | Expected OPN or HEL message on a connection "
+ "without a SecureChannel", connection->sockfd);
+ retval = UA_STATUSCODE_BADTCPMESSAGETYPEINVALID;
+ break;
+ }
+ return retval;
+}
+
+static UA_StatusCode
+processCompleteChunk(void *const application,
+ UA_Connection *const connection,
+ UA_ByteString *const chunk) {
+ UA_Server *const server = (UA_Server*)application;
+#ifdef UA_DEBUG_DUMP_PKGS_FILE
+ UA_debug_dumpCompleteChunk(server, connection, chunk);
+#endif
+ if(!connection->channel)
+ return processCompleteChunkWithoutChannel(server, connection, chunk);
+ return UA_SecureChannel_processChunk(connection->channel, chunk,
+ processSecureChannelMessage,
+ server, UA_FALSE);
+}
+
+static void
+processBinaryMessage(UA_Server *server, UA_Connection *connection,
+ UA_ByteString *message) {
+ UA_LOG_TRACE(server->config.logger, UA_LOGCATEGORY_NETWORK,
+ "Connection %i | Received a packet.", connection->sockfd);
+#ifdef UA_DEBUG_DUMP_PKGS
+ UA_dump_hex_pkg(message->data, message->length);
+#endif
+
+ UA_StatusCode retval = UA_Connection_processChunks(connection, server,
+ processCompleteChunk, message);
+ if(retval != UA_STATUSCODE_GOOD) {
+ UA_LOG_INFO(server->config.logger, UA_LOGCATEGORY_NETWORK,
+ "Connection %i | Processing the message failed with "
+ "error %s", connection->sockfd, UA_StatusCode_name(retval));
+ /* Send an ERR message and close the connection */
+ UA_TcpErrorMessage error;
+ error.error = retval;
+ error.reason = UA_STRING_NULL;
+ UA_Connection_sendError(connection, &error);
+ connection->close(connection);
+ }
+}
+
+#ifndef UA_ENABLE_MULTITHREADING
+
+void
+UA_Server_processBinaryMessage(UA_Server *server, UA_Connection *connection,
+ UA_ByteString *message) {
+ processBinaryMessage(server, connection, message);
+}
+
+#else
+
+typedef struct {
+ UA_Connection *connection;
+ UA_ByteString message;
+} ConnectionMessage;
+
+static void
+workerProcessBinaryMessage(UA_Server *server, ConnectionMessage *cm) {
+ processBinaryMessage(server, cm->connection, &cm->message);
+ UA_free(cm);
+}
+
+void
+UA_Server_processBinaryMessage(UA_Server *server, UA_Connection *connection,
+ UA_ByteString *message) {
+ /* Allocate the memory for the callback data */
+ ConnectionMessage *cm = (ConnectionMessage*)UA_malloc(sizeof(ConnectionMessage));
+
+ /* If malloc failed, execute immediately */
+ if(!cm) {
+ processBinaryMessage(server, connection, message);
+ return;
+ }
+
+ /* Dispatch to the workers */
+ cm->connection = connection;
+ cm->message = *message;
+ UA_Server_workerCallback(server, (UA_ServerCallback)workerProcessBinaryMessage, cm);
+}
+
+static void
+deleteConnectionTrampoline(UA_Server *server, void *data) {
+ UA_Connection *connection = (UA_Connection*)data;
+ connection->free(connection);
+}
+#endif
+
+void
+UA_Server_removeConnection(UA_Server *server, UA_Connection *connection) {
+ UA_Connection_detachSecureChannel(connection);
+#ifndef UA_ENABLE_MULTITHREADING
+ connection->free(connection);
+#else
+ UA_Server_delayedCallback(server, deleteConnectionTrampoline, connection);
+#endif
+}
+
+/*********************************** amalgamated original file "/home/jvoe/open62541/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
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * Copyright 2016-2017 (c) Julius Pfrommer, Fraunhofer IOSB
+ * Copyright 2016 (c) Lorenz Haas
+ * Copyright 2017 (c) frax2222
+ * Copyright 2017 (c) Florian Palm
+ * Copyright 2017-2018 (c) Stefan Profanter, fortiss GmbH
+ * Copyright 2017 (c) Julian Grothoff
+ */
+
+
+#define UA_MAX_TREE_RECURSE 50 /* How deep up/down the tree do we recurse at most? */
+
+/**********************/
+/* Parse NumericRange */
+/**********************/
+
+static size_t
+readDimension(UA_Byte *buf, size_t buflen, UA_NumericRangeDimension *dim) {
+ size_t progress = UA_readNumber(buf, buflen, &dim->min);
+ if(progress == 0)
+ return 0;
+ if(buflen <= progress + 1 || buf[progress] != ':') {
+ dim->max = dim->min;
+ return progress;
+ }
+
+ ++progress;
+ size_t progress2 = UA_readNumber(&buf[progress], buflen - progress, &dim->max);
+ if(progress2 == 0)
+ return 0;
+
+ /* invalid range */
+ if(dim->min >= dim->max)
+ return 0;
+
+ return progress + progress2;
+}
+
+UA_StatusCode
+UA_NumericRange_parseFromString(UA_NumericRange *range, const UA_String *str) {
+ size_t idx = 0;
+ size_t dimensionsMax = 0;
+ UA_NumericRangeDimension *dimensions = NULL;
+ UA_StatusCode retval = UA_STATUSCODE_GOOD;
+ size_t offset = 0;
+ while(true) {
+ /* alloc dimensions */
+ if(idx >= dimensionsMax) {
+ UA_NumericRangeDimension *newds;
+ size_t newdssize = sizeof(UA_NumericRangeDimension) * (dimensionsMax + 2);
+ newds = (UA_NumericRangeDimension*)UA_realloc(dimensions, newdssize);
+ if(!newds) {
+ retval = UA_STATUSCODE_BADOUTOFMEMORY;
+ break;
+ }
+ dimensions = newds;
+ dimensionsMax = dimensionsMax + 2;
+ }
+
+ /* read the dimension */
+ size_t progress = readDimension(&str->data[offset], str->length - offset,
+ &dimensions[idx]);
+ if(progress == 0) {
+ retval = UA_STATUSCODE_BADINDEXRANGEINVALID;
+ break;
+ }
+ offset += progress;
+ ++idx;
+
+ /* loop into the next dimension */
+ if(offset >= str->length)
+ break;
+
+ if(str->data[offset] != ',') {
+ retval = UA_STATUSCODE_BADINDEXRANGEINVALID;
+ break;
+ }
+ ++offset;
+ }
+
+ if(retval == UA_STATUSCODE_GOOD && idx > 0) {
+ range->dimensions = dimensions;
+ range->dimensionsSize = idx;
+ } else
+ UA_free(dimensions);
+
+ return retval;
+}
+
+/********************************/
+/* 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_Nodestore *ns, 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 = ns->getNode(ns->context, 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->targetIdsSize; ++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 = UA_FALSE;
+ while(!skip && last) {
+ if(UA_NodeId_equal(last->id, &refs->targetIds[j].nodeId))
+ skip = UA_TRUE;
+ last = last->parent;
+ }
+ if(skip)
+ continue;
+ }
+
+ /* Stack-allocate the visitedRefs structure for the next depth */
+ struct ref_history nextVisitedRefs = {visitedRefs, &refs->targetIds[j].nodeId,
+ (UA_UInt16)(visitedRefs->depth+1)};
+
+ /* Recurse */
+ UA_Boolean foundRecursive =
+ isNodeInTreeNoCircular(ns, &refs->targetIds[j].nodeId, nodeToFind, &nextVisitedRefs,
+ referenceTypeIds, referenceTypeIdsSize);
+ if(foundRecursive) {
+ ns->releaseNode(ns->context, node);
+ return true;
+ }
+ }
+ }
+
+ ns->releaseNode(ns->context, node);
+ return false;
+}
+
+UA_Boolean
+isNodeInTree(UA_Nodestore *ns, const UA_NodeId *leafNode, const UA_NodeId *nodeToFind,
+ const UA_NodeId *referenceTypeIds, size_t referenceTypeIdsSize) {
+ struct ref_history visitedRefs = {NULL, leafNode, 0};
+ return isNodeInTreeNoCircular(ns, leafNode, nodeToFind, &visitedRefs, referenceTypeIds, referenceTypeIdsSize);
+}
+
+const UA_Node *
+getNodeType(UA_Server *server, const UA_Node *node) {
+ /* The reference to the parent is different for variable and variabletype */
+ UA_NodeId parentRef;
+ UA_Boolean inverse;
+ UA_NodeClass typeNodeClass;
+ switch(node->nodeClass) {
+ case UA_NODECLASS_OBJECT:
+ parentRef = UA_NODEID_NUMERIC(0, UA_NS0ID_HASTYPEDEFINITION);
+ inverse = false;
+ typeNodeClass = UA_NODECLASS_OBJECTTYPE;
+ break;
+ case UA_NODECLASS_VARIABLE:
+ parentRef = UA_NODEID_NUMERIC(0, UA_NS0ID_HASTYPEDEFINITION);
+ inverse = false;
+ typeNodeClass = UA_NODECLASS_VARIABLETYPE;
+ break;
+ case UA_NODECLASS_OBJECTTYPE:
+ case UA_NODECLASS_VARIABLETYPE:
+ case UA_NODECLASS_REFERENCETYPE:
+ case UA_NODECLASS_DATATYPE:
+ parentRef = UA_NODEID_NUMERIC(0, UA_NS0ID_HASSUBTYPE);
+ inverse = true;
+ typeNodeClass = node->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))
+ continue;
+ UA_assert(node->references[i].targetIdsSize > 0);
+ const UA_NodeId *targetId = &node->references[i].targetIds[0].nodeId;
+ const UA_Node *type = UA_Nodestore_get(server, targetId);
+ if(!type)
+ continue;
+ if(type->nodeClass == typeNodeClass)
+ return type;
+ 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))
+ return true;
+ if(node->references[i].isInverse == true &&
+ UA_NodeId_equal(&node->references[i].referenceTypeId, &hasTypeDefinition))
+ return true;
+ }
+ return false;
+}
+
+static const UA_NodeId hasSubtypeNodeId =
+ {0, UA_NODEIDTYPE_NUMERIC, {UA_NS0ID_HASSUBTYPE}};
+
+static UA_StatusCode
+getTypeHierarchyFromNode(UA_NodeId **results_ptr, size_t *results_count,
+ size_t *results_size, const UA_Node *node) {
+ UA_NodeId *results = *results_ptr;
+ for(size_t i = 0; i < node->referencesSize; ++i) {
+ /* Is the reference kind relevant? */
+ UA_NodeReferenceKind *refs = &node->references[i];
+ if(!refs->isInverse)
+ continue;
+ if(!UA_NodeId_equal(&hasSubtypeNodeId, &refs->referenceTypeId))
+ continue;
+
+ /* Append all targets of the reference kind .. if not a duplicate */
+ for(size_t j = 0; j < refs->targetIdsSize; ++j) {
+ /* Is the target a duplicate? (multi-inheritance) */
+ UA_NodeId *targetId = &refs->targetIds[j].nodeId;
+ UA_Boolean duplicate = false;
+ for(size_t k = 0; k < *results_count; ++k) {
+ if(UA_NodeId_equal(targetId, &results[k])) {
+ duplicate = true;
+ break;
+ }
+ }
+ if(duplicate)
+ continue;
+
+ /* Increase array length if necessary */
+ if(*results_count >= *results_size) {
+ size_t new_size = sizeof(UA_NodeId) * (*results_size) * 2;
+ UA_NodeId *new_results = (UA_NodeId*)UA_realloc(results, new_size);
+ if(!new_results) {
+ UA_Array_delete(results, *results_count, &UA_TYPES[UA_TYPES_NODEID]);
+ return UA_STATUSCODE_BADOUTOFMEMORY;
+ }
+ results = new_results;
+ *results_ptr = results;
+ *results_size *= 2;
+ }
+
+ /* Copy new nodeid to the end of the list */
+ UA_StatusCode retval = UA_NodeId_copy(targetId, &results[*results_count]);
+ if(retval != UA_STATUSCODE_GOOD) {
+ UA_Array_delete(results, *results_count, &UA_TYPES[UA_TYPES_NODEID]);
+ return retval;
+ }
+ *results_count += 1;
+ }
+ }
+ return UA_STATUSCODE_GOOD;
+}
+
+UA_StatusCode
+getTypeHierarchy(UA_Nodestore *ns, const UA_NodeId *leafType,
+ UA_NodeId **typeHierarchy, size_t *typeHierarchySize) {
+ /* Allocate the results array. Probably too big, but saves mallocs. */
+ size_t results_size = 20;
+ UA_NodeId *results = (UA_NodeId*)UA_malloc(sizeof(UA_NodeId) * results_size);
+ if(!results)
+ return UA_STATUSCODE_BADOUTOFMEMORY;
+
+ /* The leaf is the first element */
+ size_t results_count = 1;
+ UA_StatusCode retval = UA_NodeId_copy(leafType, &results[0]);
+ if(retval != UA_STATUSCODE_GOOD) {
+ UA_free(results);
+ return retval;
+ }
+
+ /* Loop over the array members .. and add new elements to the end */
+ for(size_t idx = 0; idx < results_count; ++idx) {
+ /* Get the node */
+ const UA_Node *node = ns->getNode(ns->context, &results[idx]);
+
+ /* Invalid node, remove from the array */
+ if(!node) {
+ for(size_t i = idx; i < results_count-1; ++i)
+ results[i] = results[i+1];
+ results_count--;
+ continue;
+ }
+
+ /* Add references from the current node to the end of the array */
+ retval = getTypeHierarchyFromNode(&results, &results_count,
+ &results_size, node);
+
+ /* Release the node */
+ ns->releaseNode(ns->context, node);
+
+ if(retval != UA_STATUSCODE_GOOD) {
+ UA_Array_delete(results, results_count, &UA_TYPES[UA_TYPES_NODEID]);
+ return retval;
+ }
+ }
+
+ /* Zero results. The leaf node was not found */
+ if(results_count == 0) {
+ UA_free(results);
+ results = NULL;
+ }
+
+ *typeHierarchy = results;
+ *typeHierarchySize = results_count;
+ return UA_STATUSCODE_GOOD;
+}
+
+/* For mulithreading: make a copy of the node, edit and replace.
+ * For singlethreading: edit the original */
+UA_StatusCode
+UA_Server_editNode(UA_Server *server, UA_Session *session,
+ const UA_NodeId *nodeId, UA_EditNodeCallback callback,
+ void *data) {
+#ifndef UA_ENABLE_MULTITHREADING
+ const UA_Node *node = UA_Nodestore_get(server, nodeId);
+ if(!node)
+ return UA_STATUSCODE_BADNODEIDUNKNOWN;
+ UA_StatusCode retval = callback(server, session,
+ (UA_Node*)(uintptr_t)node, data);
+ UA_Nodestore_release(server, node);
+ return retval;
+#else
+ UA_StatusCode retval;
+ do {
+ UA_Node *node;
+ retval = server->config.nodestore.getNodeCopy(server->config.nodestore.context,
+ nodeId, &node);
+ if(retval != UA_STATUSCODE_GOOD)
+ return retval;
+ retval = callback(server, session, node, data);
+ if(retval != UA_STATUSCODE_GOOD) {
+ server->config.nodestore.deleteNode(server->config.nodestore.context, node);
+ return retval;
+ }
+ retval = server->config.nodestore.replaceNode(server->config.nodestore.context, node);
+ } while(retval != UA_STATUSCODE_GOOD);
+ return retval;
+#endif
+}
+
+UA_StatusCode
+UA_Server_processServiceOperations(UA_Server *server, UA_Session *session,
+ UA_ServiceOperation operationCallback,
+ void *context, const size_t *requestOperations,
+ const UA_DataType *requestOperationsType,
+ size_t *responseOperations,
+ const UA_DataType *responseOperationsType) {
+ size_t ops = *requestOperations;
+ if(ops == 0)
+ return UA_STATUSCODE_BADNOTHINGTODO;
+
+ /* No padding after size_t */
+ void **respPos = (void**)((uintptr_t)responseOperations + sizeof(size_t));
+ *respPos = UA_Array_new(ops, responseOperationsType);
+ if(!(*respPos))
+ return UA_STATUSCODE_BADOUTOFMEMORY;
+
+ *responseOperations = ops;
+ uintptr_t respOp = (uintptr_t)*respPos;
+ /* No padding after size_t */
+ uintptr_t reqOp = *(uintptr_t*)((uintptr_t)requestOperations + sizeof(size_t));
+ for(size_t i = 0; i < ops; i++) {
+ operationCallback(server, session, context, (void*)reqOp, (void*)respOp);
+ reqOp += requestOperationsType->memSize;
+ respOp += responseOperationsType->memSize;
+ }
+ return UA_STATUSCODE_GOOD;
+}
+
+/*********************************/
+/* Default attribute definitions */
+/*********************************/
+
+const UA_ObjectAttributes UA_ObjectAttributes_default = {
+ 0, /* specifiedAttributes */
+ {{0, NULL}, {0, NULL}}, /* displayName */
+ {{0, NULL}, {0, NULL}}, /* description */
+ 0, 0, /* writeMask (userWriteMask) */
+ 0 /* eventNotifier */
+};
+
+const UA_VariableAttributes UA_VariableAttributes_default = {
+ 0, /* specifiedAttributes */
+ {{0, NULL}, {0, NULL}}, /* displayName */
+ {{0, NULL}, {0, NULL}}, /* description */
+ 0, 0, /* writeMask (userWriteMask) */
+ {NULL, UA_VARIANT_DATA,
+ 0, NULL, 0, NULL}, /* value */
+ {0, UA_NODEIDTYPE_NUMERIC,
+ {UA_NS0ID_BASEDATATYPE}}, /* dataType */
+ UA_VALUERANK_ANY, /* valueRank */
+ 0, NULL, /* arrayDimensions */
+ UA_ACCESSLEVELMASK_READ, 0, /* accessLevel (userAccessLevel) */
+ 0.0, /* minimumSamplingInterval */
+ false /* historizing */
+};
+
+const UA_MethodAttributes UA_MethodAttributes_default = {
+ 0, /* specifiedAttributes */
+ {{0, NULL}, {0, NULL}}, /* displayName */
+ {{0, NULL}, {0, NULL}}, /* description */
+ 0, 0, /* writeMask (userWriteMask) */
+ true, true /* executable (userExecutable) */
+};
+
+const UA_ObjectTypeAttributes UA_ObjectTypeAttributes_default = {
+ 0, /* specifiedAttributes */
+ {{0, NULL}, {0, NULL}}, /* displayName */
+ {{0, NULL}, {0, NULL}}, /* description */
+ 0, 0, /* writeMask (userWriteMask) */
+ false /* isAbstract */
+};
+
+const UA_VariableTypeAttributes UA_VariableTypeAttributes_default = {
+ 0, /* specifiedAttributes */
+ {{0, NULL}, {0, NULL}}, /* displayName */
+ {{0, NULL}, {0, NULL}}, /* description */
+ 0, 0, /* writeMask (userWriteMask) */
+ {NULL, UA_VARIANT_DATA,
+ 0, NULL, 0, NULL}, /* value */
+ {0, UA_NODEIDTYPE_NUMERIC,
+ {UA_NS0ID_BASEDATATYPE}}, /* dataType */
+ UA_VALUERANK_ANY, /* valueRank */
+ 0, NULL, /* arrayDimensions */
+ false /* isAbstract */
+};
+
+const UA_ReferenceTypeAttributes UA_ReferenceTypeAttributes_default = {
+ 0, /* specifiedAttributes */
+ {{0, NULL}, {0, NULL}}, /* displayName */
+ {{0, NULL}, {0, NULL}}, /* description */
+ 0, 0, /* writeMask (userWriteMask) */
+ false, /* isAbstract */
+ false, /* symmetric */
+ {{0, NULL}, {0, NULL}} /* inverseName */
+};
+
+const UA_DataTypeAttributes UA_DataTypeAttributes_default = {
+ 0, /* specifiedAttributes */
+ {{0, NULL}, {0, NULL}}, /* displayName */
+ {{0, NULL}, {0, NULL}}, /* description */
+ 0, 0, /* writeMask (userWriteMask) */
+ false /* isAbstract */
+};
+
+const UA_ViewAttributes UA_ViewAttributes_default = {
+ 0, /* specifiedAttributes */
+ {{0, NULL}, {0, NULL}}, /* displayName */
+ {{0, NULL}, {0, NULL}}, /* description */
+ 0, 0, /* writeMask (userWriteMask) */
+ false, /* containsNoLoops */
+ 0 /* eventNotifier */
+};
+
+
+/*********************************** amalgamated original file "/home/jvoe/open62541/src/server/ua_server_worker.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-2017 (c) Julius Pfrommer, Fraunhofer IOSB
+ * 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
+ */
+
+#ifdef UA_ENABLE_VALGRIND_INTERACTIVE
+#include <valgrind/memcheck.h>
+#endif
+
+#define UA_MAXTIMEOUT 50 /* Max timeout in ms between main-loop iterations */
+
+/**
+ * Worker Threads and Dispatch Queue
+ * ---------------------------------
+ * The worker threads dequeue callbacks from a central Multi-Producer
+ * Multi-Consumer Queue (MPMC). When there are no callbacks, workers go idle.
+ * The condition to wake them up is triggered whenever a callback is
+ * dispatched.
+ *
+ * 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. */
+
+#ifdef UA_ENABLE_MULTITHREADING
+
+struct UA_Worker {
+ UA_Server *server;
+ pthread_t thr;
+ UA_UInt32 counter;
+ volatile UA_Boolean running;
+
+ /* separate cache lines */
+ char padding[64 - sizeof(void*) - sizeof(pthread_t) -
+ sizeof(UA_UInt32) - sizeof(UA_Boolean)];
+};
+
+struct UA_WorkerCallback {
+ SIMPLEQ_ENTRY(UA_WorkerCallback) next;
+ UA_ServerCallback callback;
+ void *data;
+
+ UA_Boolean delayed; /* Is it a delayed callback? */
+ UA_Boolean countersSampled; /* Have the worker counters been sampled? */
+ UA_UInt32 workerCounters[]; /* Counter value for each worker */
+};
+typedef struct UA_WorkerCallback WorkerCallback;
+
+/* Forward Declaration */
+static void
+processDelayedCallback(UA_Server *server, WorkerCallback *dc);
+
+static void *
+workerLoop(UA_Worker *worker) {
+ UA_Server *server = worker->server;
+ 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);
+
+ while(*running) {
+ UA_atomic_addUInt32(counter, 1);
+ pthread_mutex_lock(&server->dispatchQueue_accessMutex);
+ WorkerCallback *dc = SIMPLEQ_FIRST(&server->dispatchQueue);
+ if(dc) {
+ SIMPLEQ_REMOVE_HEAD(&server->dispatchQueue, next);
+ }
+ pthread_mutex_unlock(&server->dispatchQueue_accessMutex);
+ if(!dc) {
+ /* Nothing to do. Sleep until a callback is dispatched */
+ pthread_mutex_lock(&server->dispatchQueue_conditionMutex);
+ pthread_cond_wait(&server->dispatchQueue_condition,
+ &server->dispatchQueue_conditionMutex);
+ pthread_mutex_unlock(&server->dispatchQueue_conditionMutex);
+ continue;
+ }
+
+ if(dc->delayed) {
+ processDelayedCallback(server, dc);
+ continue;
+ }
+
+ dc->callback(server, dc->data);
+ UA_free(dc);
+ }
+
+ UA_LOG_DEBUG(server->config.logger, UA_LOGCATEGORY_SERVER,
+ "Worker shut down");
+ return NULL;
+}
+
+void UA_Server_cleanupDispatchQueue(UA_Server *server) {
+ while(true) {
+ pthread_mutex_lock(&server->dispatchQueue_accessMutex);
+ WorkerCallback *dc = SIMPLEQ_FIRST(&server->dispatchQueue);
+ if(!dc) {
+ pthread_mutex_unlock(&server->dispatchQueue_accessMutex);
+ break;
+ }
+ SIMPLEQ_REMOVE_HEAD(&server->dispatchQueue, next);
+ pthread_mutex_unlock(&server->dispatchQueue_accessMutex);
+ dc->callback(server, dc->data);
+ UA_free(dc);
+ }
+}
+
+#endif
+
+/**
+ * Repeated Callbacks
+ * ------------------
+ * Repeated Callbacks are handled by UA_Timer (used in both client and server).
+ * In the multi-threaded case, callbacks are dispatched to workers. Otherwise,
+ * they are executed immediately. */
+
+void
+UA_Server_workerCallback(UA_Server *server, UA_ServerCallback callback,
+ void *data) {
+#ifndef UA_ENABLE_MULTITHREADING
+ /* Execute immediately */
+ callback(server, data);
+#else
+ /* Execute immediately if memory could not be allocated */
+ WorkerCallback *dc = (WorkerCallback*)UA_malloc(sizeof(WorkerCallback));
+ if(!dc) {
+ callback(server, data);
+ return;
+ }
+
+ /* Enqueue for the worker threads */
+ dc->callback = callback;
+ dc->data = data;
+ dc->delayed = false;
+ pthread_mutex_lock(&server->dispatchQueue_accessMutex);
+ SIMPLEQ_INSERT_TAIL(&server->dispatchQueue, dc, next);
+ pthread_mutex_unlock(&server->dispatchQueue_accessMutex);
+
+ /* Wake up sleeping workers */
+ pthread_cond_broadcast(&server->dispatchQueue_condition);
+#endif
+}
+
+/**
+ * Delayed Callbacks
+ * -----------------
+ *
+ * Delayed Callbacks are called only when all callbacks that were dispatched
+ * prior are finished. In the single-threaded case, the callback is added to a
+ * singly-linked list that is processed at the end of the server's main-loop. In
+ * the multi-threaded case, the delay is ensure by a three-step procedure:
+ *
+ * 1. The delayed callback is dispatched to the worker queue. So it is only
+ * dequeued when all prior callbacks have been dequeued.
+ *
+ * 2. When the callback is first dequeued by a worker, sample the counter of all
+ * workers. Once all counters have advanced, the callback is ready.
+ *
+ * 3. Check regularly if the callback is ready by adding it back to the dispatch
+ * queue. */
+
+/* Delayed callback to free the subscription memory */
+static void
+freeCallback(UA_Server *server, void *data) {
+ UA_free(data);
+}
+
+/* TODO: Delayed free should never fail. This can be achieved by adding a prefix
+ * with the list pointers */
+UA_StatusCode
+UA_Server_delayedFree(UA_Server *server, void *data) {
+ return UA_Server_delayedCallback(server, freeCallback, data);
+}
+
+#ifndef UA_ENABLE_MULTITHREADING
+
+typedef struct UA_DelayedCallback {
+ SLIST_ENTRY(UA_DelayedCallback) next;
+ UA_ServerCallback callback;
+ void *data;
+} UA_DelayedCallback;
+
+UA_StatusCode
+UA_Server_delayedCallback(UA_Server *server, UA_ServerCallback callback,
+ void *data) {
+ UA_DelayedCallback *dc =
+ (UA_DelayedCallback*)UA_malloc(sizeof(UA_DelayedCallback));
+ if(!dc)
+ return UA_STATUSCODE_BADOUTOFMEMORY;
+
+ dc->callback = callback;
+ dc->data = data;
+ SLIST_INSERT_HEAD(&server->delayedCallbacks, dc, next);
+ return UA_STATUSCODE_GOOD;
+}
+
+void UA_Server_cleanupDelayedCallbacks(UA_Server *server) {
+ UA_DelayedCallback *dc, *dc_tmp;
+ SLIST_FOREACH_SAFE(dc, &server->delayedCallbacks, next, dc_tmp) {
+ SLIST_REMOVE(&server->delayedCallbacks, dc, UA_DelayedCallback, next);
+ dc->callback(server, dc->data);
+ UA_free(dc);
+ }
+}
+
+#else /* UA_ENABLE_MULTITHREADING */
+
+UA_StatusCode
+UA_Server_delayedCallback(UA_Server *server, UA_ServerCallback callback,
+ void *data) {
+ size_t dcsize = sizeof(WorkerCallback) +
+ (sizeof(UA_UInt32) * server->config.nThreads);
+ WorkerCallback *dc = (WorkerCallback*)UA_malloc(dcsize);
+ if(!dc)
+ return UA_STATUSCODE_BADOUTOFMEMORY;
+
+ /* Enqueue for the worker threads */
+ dc->callback = callback;
+ dc->data = data;
+ dc->delayed = true;
+ dc->countersSampled = false;
+ pthread_mutex_lock(&server->dispatchQueue_accessMutex);
+ SIMPLEQ_INSERT_TAIL(&server->dispatchQueue, dc, next);
+ pthread_mutex_unlock(&server->dispatchQueue_accessMutex);
+
+ /* Wake up sleeping workers */
+ pthread_cond_broadcast(&server->dispatchQueue_condition);
+ return UA_STATUSCODE_GOOD;
+}
+
+/* Called from the worker loop */
+static void
+processDelayedCallback(UA_Server *server, WorkerCallback *dc) {
+ /* Set the worker counters */
+ if(!dc->countersSampled) {
+ for(size_t i = 0; i < server->config.nThreads; ++i)
+ dc->workerCounters[i] = server->workers[i].counter;
+ dc->countersSampled = true;
+
+ /* Re-add to the dispatch queue */
+ pthread_mutex_lock(&server->dispatchQueue_accessMutex);
+ SIMPLEQ_INSERT_TAIL(&server->dispatchQueue, dc, next);
+ pthread_mutex_unlock(&server->dispatchQueue_accessMutex);
+
+ /* Wake up sleeping workers */
+ pthread_cond_broadcast(&server->dispatchQueue_condition);
+ return;
+ }
+
+ /* Have all other jobs finished? */
+ UA_Boolean ready = true;
+ for(size_t i = 0; i < server->config.nThreads; ++i) {
+ if(dc->workerCounters[i] == server->workers[i].counter) {
+ ready = false;
+ break;
+ }
+ }
+
+ /* Re-add to the dispatch queue.
+ * TODO: What is the impact of this loop?
+ * Can we add a small delay here? */
+ if(!ready) {
+ pthread_mutex_lock(&server->dispatchQueue_accessMutex);
+ SIMPLEQ_INSERT_TAIL(&server->dispatchQueue, dc, next);
+ pthread_mutex_unlock(&server->dispatchQueue_accessMutex);
+
+ /* Wake up sleeping workers */
+ pthread_cond_broadcast(&server->dispatchQueue_condition);
+ return;
+ }
+
+ /* Execute the callback */
+ dc->callback(server, dc->data);
+ UA_free(dc);
+}
+
+#endif
+
+/**
+ * Main Server Loop
+ * ----------------
+ * Start: Spin up the workers and the network layer and sample the server's
+ * start time.
+ * Iterate: Process repeated callbacks and events in the network layer.
+ * This part can be driven from an external main-loop in an
+ * event-driven single-threaded architecture.
+ * Stop: Stop workers, finish all callbacks, stop the network layer,
+ * clean up */
+
+UA_StatusCode
+UA_Server_run_startup(UA_Server *server) {
+ UA_Variant var;
+ UA_StatusCode result = UA_STATUSCODE_GOOD;
+
+ /* Sample the start time and set it to the Server object */
+ server->startTime = UA_DateTime_now();
+ UA_Variant_init(&var);
+ UA_Variant_setScalar(&var, &server->startTime, &UA_TYPES[UA_TYPES_DATETIME]);
+ UA_Server_writeValue(server,
+ UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERSTATUS_STARTTIME),
+ var);
+
+ /* Start the networklayers */
+ for(size_t i = 0; i < server->config.networkLayersSize; ++i) {
+ UA_ServerNetworkLayer *nl = &server->config.networkLayers[i];
+ result |= nl->start(nl, &server->config.customHostname);
+ }
+
+ /* Spin up the worker threads */
+#ifdef UA_ENABLE_MULTITHREADING
+ UA_LOG_INFO(server->config.logger, UA_LOGCATEGORY_SERVER,
+ "Spinning up %u worker thread(s)", server->config.nThreads);
+ pthread_mutex_init(&server->dispatchQueue_accessMutex, NULL);
+ pthread_cond_init(&server->dispatchQueue_condition, NULL);
+ pthread_mutex_init(&server->dispatchQueue_conditionMutex, NULL);
+ server->workers = (UA_Worker*)UA_malloc(server->config.nThreads * sizeof(UA_Worker));
+ if(!server->workers)
+ return UA_STATUSCODE_BADOUTOFMEMORY;
+ for(size_t i = 0; i < server->config.nThreads; ++i) {
+ UA_Worker *worker = &server->workers[i];
+ worker->server = server;
+ worker->counter = 0;
+ worker->running = true;
+ pthread_create(&worker->thr, NULL, (void* (*)(void*))workerLoop, worker);
+ }
+#endif
+
+ /* Start the multicast discovery server */
+#ifdef UA_ENABLE_DISCOVERY_MULTICAST
+ if(server->config.applicationDescription.applicationType ==
+ UA_APPLICATIONTYPE_DISCOVERYSERVER)
+ startMulticastDiscoveryServer(server);
+#endif
+
+ return result;
+}
+
+UA_UInt16
+UA_Server_run_iterate(UA_Server *server, UA_Boolean waitInternal) {
+ /* Process repeated work */
+ UA_DateTime now = UA_DateTime_nowMonotonic();
+ UA_DateTime nextRepeated =
+ UA_Timer_process(&server->timer, now,
+ (UA_TimerDispatchCallback)UA_Server_workerCallback,
+ server);
+ UA_DateTime latest = now + (UA_MAXTIMEOUT * UA_DATETIME_MSEC);
+ if(nextRepeated > latest)
+ nextRepeated = latest;
+
+ UA_UInt16 timeout = 0;
+
+ /* round always to upper value to avoid timeout to be set to 0
+ * if(nextRepeated - now) < (UA_DATETIME_MSEC/2) */
+ if(waitInternal)
+ timeout = (UA_UInt16)(((nextRepeated - now) + (UA_DATETIME_MSEC - 1)) / UA_DATETIME_MSEC);
+
+ /* Listen on the networklayer */
+ for(size_t i = 0; i < server->config.networkLayersSize; ++i) {
+ UA_ServerNetworkLayer *nl = &server->config.networkLayers[i];
+ nl->listen(nl, server, timeout);
+ }
+
+#ifndef UA_ENABLE_MULTITHREADING
+ /* Process delayed callbacks when all callbacks and network events are done.
+ * If multithreading is enabled, the cleanup of delayed values is attempted
+ * by a callback in the job queue. */
+ UA_Server_cleanupDelayedCallbacks(server);
+#endif
+
+#if defined(UA_ENABLE_DISCOVERY_MULTICAST) && !defined(UA_ENABLE_MULTITHREADING)
+ if(server->config.applicationDescription.applicationType ==
+ UA_APPLICATIONTYPE_DISCOVERYSERVER) {
+ // 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, UA_TRUE);
+ if(hasNext == UA_STATUSCODE_GOOD && multicastNextRepeat < nextRepeated)
+ nextRepeated = multicastNextRepeat;
+ }
+#endif
+
+ now = UA_DateTime_nowMonotonic();
+ timeout = 0;
+ if(nextRepeated > now)
+ timeout = (UA_UInt16)((nextRepeated - now) / UA_DATETIME_MSEC);
+ return timeout;
+}
+
+UA_StatusCode
+UA_Server_run_shutdown(UA_Server *server) {
+ /* Stop the netowrk layer */
+ for(size_t i = 0; i < server->config.networkLayersSize; ++i) {
+ UA_ServerNetworkLayer *nl = &server->config.networkLayers[i];
+ nl->stop(nl, server);
+ }
+
+#ifdef UA_ENABLE_MULTITHREADING
+ /* Shut down the workers */
+ if(server->workers) {
+ UA_LOG_INFO(server->config.logger, UA_LOGCATEGORY_SERVER,
+ "Shutting down %u worker thread(s)",
+ server->config.nThreads);
+ for(size_t i = 0; i < server->config.nThreads; ++i)
+ server->workers[i].running = false;
+ pthread_cond_broadcast(&server->dispatchQueue_condition);
+ for(size_t i = 0; i < server->config.nThreads; ++i)
+ pthread_join(server->workers[i].thr, NULL);
+ UA_free(server->workers);
+ server->workers = NULL;
+ }
+
+ /* Execute the remaining callbacks in the dispatch queue. Also executes
+ * delayed callbacks. */
+ UA_Server_cleanupDispatchQueue(server);
+#else
+ /* Process remaining delayed callbacks */
+ UA_Server_cleanupDelayedCallbacks(server);
+#endif
+
+#ifdef UA_ENABLE_DISCOVERY_MULTICAST
+ /* Stop multicast discovery */
+ if(server->config.applicationDescription.applicationType ==
+ UA_APPLICATIONTYPE_DISCOVERYSERVER)
+ stopMulticastDiscoveryServer(server);
+#endif
+
+ return UA_STATUSCODE_GOOD;
+}
+
+UA_StatusCode
+UA_Server_run(UA_Server *server, volatile UA_Boolean *running) {
+ UA_StatusCode retval = UA_Server_run_startup(server);
+ if(retval != UA_STATUSCODE_GOOD)
+ return retval;
+#ifdef UA_ENABLE_VALGRIND_INTERACTIVE
+ size_t loopCount = 0;
+#endif
+ while(*running) {
+#ifdef UA_ENABLE_VALGRIND_INTERACTIVE
+ if(loopCount == 0) {
+ VALGRIND_DO_LEAK_CHECK;
+ }
+ ++loopCount;
+ loopCount %= UA_VALGRIND_INTERACTIVE_INTERVAL;
+#endif
+ UA_Server_run_iterate(server, true);
+ }
+ return UA_Server_run_shutdown(server);
+}
+
+/*********************************** amalgamated original file "/home/jvoe/open62541/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
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * Copyright 2017 (c) Julius Pfrommer, Fraunhofer IOSB
+ * Copyright 2017 (c) Stefan Profanter, fortiss GmbH
+ */
+
+
+#ifdef UA_ENABLE_DISCOVERY
+
+static UA_StatusCode
+register_server_with_discovery_server(UA_Server *server,
+ const char* discoveryServerUrl,
+ const UA_Boolean isUnregister,
+ const char* semaphoreFilePath) {
+ if(!discoveryServerUrl) {
+ UA_LOG_ERROR(server->config.logger, UA_LOGCATEGORY_SERVER,
+ "No discovery server url provided");
+ return UA_STATUSCODE_BADINTERNALERROR;
+ }
+
+ /* Create the client */
+ UA_ClientConfig clientConfig = UA_Server_getClientConfig();
+ UA_Client *client = UA_Client_new(clientConfig);
+ if(!client)
+ return UA_STATUSCODE_BADOUTOFMEMORY;
+
+ /* Connect the client */
+ UA_StatusCode retval = UA_Client_connect(client, discoveryServerUrl);
+ if(retval != UA_STATUSCODE_GOOD) {
+ UA_LOG_ERROR(server->config.logger, UA_LOGCATEGORY_CLIENT,
+ "Connecting to the discovery server failed with statuscode %s",
+ UA_StatusCode_name(retval));
+ UA_Client_disconnect(client);
+ UA_Client_delete(client);
+ return retval;
+ }
+
+ /* Prepare the request. Do not cleanup the request after the service call,
+ * as the members are stack-allocated or point into the server config. */
+ UA_RegisterServer2Request request;
+ UA_RegisterServer2Request_init(&request);
+ request.requestHeader.timestamp = UA_DateTime_now();
+ request.requestHeader.timeoutHint = 10000;
+
+ request.server.isOnline = !isUnregister;
+ request.server.serverUri = server->config.applicationDescription.applicationUri;
+ request.server.productUri = server->config.applicationDescription.productUri;
+ request.server.serverType = server->config.applicationDescription.applicationType;
+ request.server.gatewayServerUri = server->config.applicationDescription.gatewayServerUri;
+
+ if(semaphoreFilePath) {
+#ifdef UA_ENABLE_DISCOVERY_SEMAPHORE
+ request.server.semaphoreFilePath =
+ UA_STRING((char*)(uintptr_t)semaphoreFilePath); /* dirty cast */
+#else
+ UA_LOG_WARNING(server->config.logger, UA_LOGCATEGORY_CLIENT,
+ "Ignoring semaphore file path. open62541 not compiled "
+ "with UA_ENABLE_DISCOVERY_SEMAPHORE=ON");
+#endif
+ }
+
+ request.server.serverNames = &server->config.applicationDescription.applicationName;
+ request.server.serverNamesSize = 1;
+
+ /* Copy 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;
+
+ 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;
+ }
+
+ UA_MdnsDiscoveryConfiguration mdnsConfig;
+ UA_MdnsDiscoveryConfiguration_init(&mdnsConfig);
+
+ request.discoveryConfigurationSize = 1;
+ request.discoveryConfiguration = UA_ExtensionObject_new();
+ UA_ExtensionObject_init(&request.discoveryConfiguration[0]);
+ 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 = &mdnsConfig;
+
+ mdnsConfig.mdnsServerName = server->config.mdnsServerName;
+ mdnsConfig.serverCapabilities = server->config.serverCapabilities;
+ mdnsConfig.serverCapabilitiesSize = server->config.serverCapabilitiesSize;
+
+ // First try with RegisterServer2, if that isn't implemented, use RegisterServer
+ UA_RegisterServer2Response response;
+ __UA_Client_Service(client, &request, &UA_TYPES[UA_TYPES_REGISTERSERVER2REQUEST],
+ &response, &UA_TYPES[UA_TYPES_REGISTERSERVER2RESPONSE]);
+
+ UA_StatusCode serviceResult = response.responseHeader.serviceResult;
+ UA_RegisterServer2Response_deleteMembers(&response);
+ UA_ExtensionObject_delete(request.discoveryConfiguration);
+
+ if(serviceResult == UA_STATUSCODE_BADNOTIMPLEMENTED ||
+ serviceResult == UA_STATUSCODE_BADSERVICEUNSUPPORTED) {
+ /* Try RegisterServer */
+ UA_RegisterServerRequest request_fallback;
+ UA_RegisterServerRequest_init(&request_fallback);
+ /* Copy from RegisterServer2 request */
+ request_fallback.requestHeader = request.requestHeader;
+ request_fallback.server = request.server;
+
+ UA_RegisterServerResponse response_fallback;
+
+ __UA_Client_Service(client, &request_fallback,
+ &UA_TYPES[UA_TYPES_REGISTERSERVERREQUEST],
+ &response_fallback,
+ &UA_TYPES[UA_TYPES_REGISTERSERVERRESPONSE]);
+
+ serviceResult = response_fallback.responseHeader.serviceResult;
+ UA_RegisterServerResponse_deleteMembers(&response_fallback);
+ }
+
+ if(serviceResult != UA_STATUSCODE_GOOD) {
+ UA_LOG_ERROR(server->config.logger, UA_LOGCATEGORY_CLIENT,
+ "RegisterServer/RegisterServer2 failed with statuscode %s",
+ UA_StatusCode_name(serviceResult));
+ }
+
+ UA_Client_disconnect(client);
+ UA_Client_delete(client);
+ return serviceResult;
+}
+
+UA_StatusCode
+UA_Server_register_discovery(UA_Server *server, const char* discoveryServerUrl,
+ const char* semaphoreFilePath) {
+ return register_server_with_discovery_server(server, discoveryServerUrl,
+ UA_FALSE, semaphoreFilePath);
+}
+
+UA_StatusCode
+UA_Server_unregister_discovery(UA_Server *server, const char* discoveryServerUrl) {
+ return register_server_with_discovery_server(server, discoveryServerUrl,
+ UA_TRUE, NULL);
+}
+
+#endif /* UA_ENABLE_DISCOVERY */
+
+/*********************************** amalgamated original file "/home/jvoe/open62541/src/server/ua_securechannel_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
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * Copyright 2014-2017 (c) Julius Pfrommer, Fraunhofer IOSB
+ * Copyright 2014-2017 (c) Florian Palm
+ * Copyright 2015-2016 (c) Sten Grüner
+ * Copyright 2015 (c) Oleksiy Vasylyev
+ * Copyright 2017 (c) Stefan Profanter, fortiss GmbH
+ * Copyright 2017 (c) Mark Giraud, Fraunhofer IOSB
+ */
+
+
+#define STARTCHANNELID 1
+#define STARTTOKENID 1
+
+UA_StatusCode
+UA_SecureChannelManager_init(UA_SecureChannelManager *cm, UA_Server *server) {
+ TAILQ_INIT(&cm->channels);
+ // TODO: use an ID that is likely to be unique after a restart
+ cm->lastChannelId = STARTCHANNELID;
+ cm->lastTokenId = STARTTOKENID;
+ cm->currentChannelCount = 0;
+ cm->server = server;
+ return UA_STATUSCODE_GOOD;
+}
+
+void
+UA_SecureChannelManager_deleteMembers(UA_SecureChannelManager *cm) {
+ channel_entry *entry, *temp;
+ TAILQ_FOREACH_SAFE(entry, &cm->channels, pointers, temp) {
+ TAILQ_REMOVE(&cm->channels, entry, pointers);
+ UA_SecureChannel_deleteMembersCleanup(&entry->channel);
+ UA_free(entry);
+ }
+}
+
+static void
+removeSecureChannelCallback(UA_Server *server, void *entry) {
+ channel_entry *centry = (channel_entry *)entry;
+ UA_SecureChannel_deleteMembersCleanup(&centry->channel);
+ UA_free(entry);
+}
+
+static UA_StatusCode
+removeSecureChannel(UA_SecureChannelManager *cm, channel_entry *entry) {
+ /* Add a delayed callback to remove the channel when the currently
+ * scheduled jobs have completed */
+ UA_StatusCode retval = UA_Server_delayedCallback(cm->server, removeSecureChannelCallback, entry);
+ if(retval != UA_STATUSCODE_GOOD) {
+ UA_LOG_WARNING(cm->server->config.logger, UA_LOGCATEGORY_SESSION,
+ "Could not remove the secure channel with error code %s",
+ UA_StatusCode_name(retval));
+ return retval; /* Try again next time */
+ }
+
+ /* Detach the channel and make the capacity available */
+ TAILQ_REMOVE(&cm->channels, entry, pointers);
+ UA_atomic_subUInt32(&cm->currentChannelCount, 1);
+ return UA_STATUSCODE_GOOD;
+}
+
+/* remove channels that were not renewed or who have no connection attached */
+void
+UA_SecureChannelManager_cleanupTimedOut(UA_SecureChannelManager *cm, UA_DateTime nowMonotonic) {
+ channel_entry *entry, *temp;
+ TAILQ_FOREACH_SAFE(entry, &cm->channels, pointers, temp) {
+ UA_DateTime timeout = entry->channel.securityToken.createdAt +
+ (UA_DateTime)(entry->channel.securityToken.revisedLifetime * UA_DATETIME_MSEC);
+ if(timeout < nowMonotonic || !entry->channel.connection) {
+ UA_LOG_INFO_CHANNEL(cm->server->config.logger, &entry->channel,
+ "SecureChannel has timed out");
+ removeSecureChannel(cm, entry);
+ } else if(entry->channel.nextSecurityToken.tokenId > 0) {
+ UA_SecureChannel_revolveTokens(&entry->channel);
+ }
+ }
+}
+
+/* remove the first channel that has no session attached */
+static UA_Boolean
+purgeFirstChannelWithoutSession(UA_SecureChannelManager *cm) {
+ channel_entry *entry;
+ TAILQ_FOREACH(entry, &cm->channels, pointers) {
+ if(LIST_EMPTY(&entry->channel.sessions)) {
+ UA_LOG_INFO_CHANNEL(cm->server->config.logger, &entry->channel,
+ "Channel was purged since maxSecureChannels was "
+ "reached and channel had no session attached");
+ removeSecureChannel(cm, entry);
+ return true;
+ }
+ }
+ return false;
+}
+
+UA_StatusCode
+UA_SecureChannelManager_create(UA_SecureChannelManager *const cm, UA_Connection *const connection,
+ const UA_SecurityPolicy *const securityPolicy,
+ const UA_AsymmetricAlgorithmSecurityHeader *const asymHeader) {
+ /* connection already has a channel attached. */
+ if(connection->channel != NULL)
+ return UA_STATUSCODE_BADINTERNALERROR;
+
+ /* 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(cm->currentChannelCount >= cm->server->config.maxSecureChannels &&
+ !purgeFirstChannelWithoutSession(cm))
+ return UA_STATUSCODE_BADOUTOFMEMORY;
+
+ UA_LOG_INFO(cm->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;
+
+ /* Create the channel context and parse the sender (remote) certificate used for the
+ * secureChannel. */
+ UA_StatusCode retval = UA_SecureChannel_init(&entry->channel, securityPolicy,
+ &asymHeader->senderCertificate);
+ if(retval != UA_STATUSCODE_GOOD) {
+ UA_free(entry);
+ return retval;
+ }
+
+ /* Channel state is fresh (0) */
+ entry->channel.securityToken.channelId = 0;
+ entry->channel.securityToken.tokenId = cm->lastTokenId++;
+ entry->channel.securityToken.createdAt = UA_DateTime_now();
+ entry->channel.securityToken.revisedLifetime = cm->server->config.maxSecurityTokenLifetime;
+
+ TAILQ_INSERT_TAIL(&cm->channels, entry, pointers);
+ UA_atomic_addUInt32(&cm->currentChannelCount, 1);
+ UA_Connection_attachSecureChannel(connection, &entry->channel);
+ return UA_STATUSCODE_GOOD;
+}
+
+UA_StatusCode
+UA_SecureChannelManager_open(UA_SecureChannelManager *cm, UA_SecureChannel *channel,
+ const UA_OpenSecureChannelRequest *request,
+ UA_OpenSecureChannelResponse *response) {
+ if(channel->state != UA_SECURECHANNELSTATE_FRESH) {
+ UA_LOG_ERROR_CHANNEL(cm->server->config.logger, channel,
+ "Called open on already open or closed channel");
+ return UA_STATUSCODE_BADINTERNALERROR;
+ }
+
+ if(request->securityMode != UA_MESSAGESECURITYMODE_NONE &&
+ UA_ByteString_equal(&channel->securityPolicy->policyUri, &UA_SECURITY_POLICY_NONE_URI)) {
+ return UA_STATUSCODE_BADSECURITYMODEREJECTED;
+ }
+
+ channel->securityMode = request->securityMode;
+ channel->securityToken.createdAt = UA_DateTime_nowMonotonic();
+ channel->securityToken.channelId = cm->lastChannelId++;
+ channel->securityToken.createdAt = UA_DateTime_now();
+
+ /* Set the lifetime. Lifetime 0 -> set the maximum possible */
+ channel->securityToken.revisedLifetime =
+ (request->requestedLifetime > cm->server->config.maxSecurityTokenLifetime) ?
+ cm->server->config.maxSecurityTokenLifetime : request->requestedLifetime;
+ if(channel->securityToken.revisedLifetime == 0)
+ channel->securityToken.revisedLifetime = cm->server->config.maxSecurityTokenLifetime;
+
+ /* Set the nonces and generate the keys */
+ UA_StatusCode retval = UA_ByteString_copy(&request->clientNonce, &channel->remoteNonce);
+ retval |= UA_SecureChannel_generateLocalNonce(channel);
+ retval |= UA_SecureChannel_generateNewKeys(channel);
+ if(retval != UA_STATUSCODE_GOOD)
+ return retval;
+
+ /* Set the response */
+ retval = UA_ByteString_copy(&channel->localNonce, &response->serverNonce);
+ retval |= UA_ChannelSecurityToken_copy(&channel->securityToken, &response->securityToken);
+ response->responseHeader.timestamp = UA_DateTime_now();
+ response->responseHeader.requestHandle = request->requestHeader.requestHandle;
+ if(retval != UA_STATUSCODE_GOOD)
+ return retval;
+
+ /* The channel is open */
+ channel->state = UA_SECURECHANNELSTATE_OPEN;
+
+ return UA_STATUSCODE_GOOD;
+}
+
+UA_StatusCode
+UA_SecureChannelManager_renew(UA_SecureChannelManager *cm, UA_SecureChannel *channel,
+ const UA_OpenSecureChannelRequest *request,
+ UA_OpenSecureChannelResponse *response) {
+ if(channel->state != UA_SECURECHANNELSTATE_OPEN) {
+ UA_LOG_ERROR_CHANNEL(cm->server->config.logger, channel,
+ "Called renew on channel which is not open");
+ return UA_STATUSCODE_BADINTERNALERROR;
+ }
+
+ /* If no security token is already issued */
+ if(channel->nextSecurityToken.tokenId == 0) {
+ channel->nextSecurityToken.channelId = channel->securityToken.channelId;
+ channel->nextSecurityToken.tokenId = cm->lastTokenId++;
+ channel->nextSecurityToken.createdAt = UA_DateTime_now();
+ channel->nextSecurityToken.revisedLifetime =
+ (request->requestedLifetime > cm->server->config.maxSecurityTokenLifetime) ?
+ cm->server->config.maxSecurityTokenLifetime : request->requestedLifetime;
+ if(channel->nextSecurityToken.revisedLifetime == 0) /* lifetime 0 -> return the max lifetime */
+ channel->nextSecurityToken.revisedLifetime = cm->server->config.maxSecurityTokenLifetime;
+ }
+
+ /* Replace the nonces */
+ UA_ByteString_deleteMembers(&channel->remoteNonce);
+ UA_StatusCode retval = UA_ByteString_copy(&request->clientNonce, &channel->remoteNonce);
+ retval |= UA_SecureChannel_generateLocalNonce(channel);
+ if(retval != UA_STATUSCODE_GOOD)
+ return retval;
+
+ /* Set the response */
+ response->responseHeader.requestHandle = request->requestHeader.requestHandle;
+ retval = UA_ByteString_copy(&channel->localNonce, &response->serverNonce);
+ retval |= UA_ChannelSecurityToken_copy(&channel->nextSecurityToken, &response->securityToken);
+ if(retval != UA_STATUSCODE_GOOD)
+ return retval;
+
+ /* Reset the internal creation date to the monotonic clock */
+ channel->nextSecurityToken.createdAt = UA_DateTime_nowMonotonic();
+ return UA_STATUSCODE_GOOD;
+}
+
+UA_SecureChannel *
+UA_SecureChannelManager_get(UA_SecureChannelManager *cm, UA_UInt32 channelId) {
+ channel_entry *entry;
+ TAILQ_FOREACH(entry, &cm->channels, pointers) {
+ if(entry->channel.securityToken.channelId == channelId)
+ return &entry->channel;
+ }
+ return NULL;
+}
+
+UA_StatusCode
+UA_SecureChannelManager_close(UA_SecureChannelManager *cm, UA_UInt32 channelId) {
+ channel_entry *entry;
+ TAILQ_FOREACH(entry, &cm->channels, pointers) {
+ if(entry->channel.securityToken.channelId == channelId)
+ break;
+ }
+ if(!entry)
+ return UA_STATUSCODE_BADINTERNALERROR;
+ return removeSecureChannel(cm, entry);
+}
+
+/*********************************** amalgamated original file "/home/jvoe/open62541/src/server/ua_session_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
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * Copyright 2014-2017 (c) Julius Pfrommer, Fraunhofer IOSB
+ * Copyright 2014, 2017 (c) Florian Palm
+ * Copyright 2015 (c) Sten Grüner
+ * Copyright 2015 (c) Oleksiy Vasylyev
+ * Copyright 2017 (c) Stefan Profanter, fortiss GmbH
+ */
+
+
+UA_StatusCode
+UA_SessionManager_init(UA_SessionManager *sm, UA_Server *server) {
+ LIST_INIT(&sm->sessions);
+ sm->currentSessionCount = 0;
+ sm->server = server;
+ return UA_STATUSCODE_GOOD;
+}
+
+/* Delayed callback to free the session memory */
+static void
+removeSessionCallback(UA_Server *server, void *entry) {
+ session_list_entry *sentry = (session_list_entry*)entry;
+ UA_Session_deleteMembersCleanup(&sentry->session, server);
+ UA_free(sentry);
+}
+
+static UA_StatusCode
+removeSession(UA_SessionManager *sm, session_list_entry *sentry) {
+ /* Remove the Subscriptions */
+#ifdef UA_ENABLE_SUBSCRIPTIONS
+ UA_Subscription *sub, *tempsub;
+ LIST_FOREACH_SAFE(sub, &sentry->session.serverSubscriptions, listEntry, tempsub) {
+ UA_Session_deleteSubscription(sm->server, &sentry->session, sub->subscriptionId);
+ }
+
+ UA_PublishResponseEntry *entry;
+ while((entry = UA_Session_dequeuePublishReq(&sentry->session))) {
+ UA_PublishResponse_deleteMembers(&entry->response);
+ UA_free(entry);
+ }
+#endif
+
+ /* Detach the Session from the SecureChannel */
+ UA_Session_detachFromSecureChannel(&sentry->session);
+
+ /* Deactivate the session */
+ sentry->session.activated = false;
+
+ /* Add a delayed callback to remove the session when the currently
+ * scheduled jobs have completed */
+ UA_StatusCode retval = UA_Server_delayedCallback(sm->server, removeSessionCallback, sentry);
+ if(retval != UA_STATUSCODE_GOOD) {
+ UA_LOG_WARNING_SESSION(sm->server->config.logger, &sentry->session,
+ "Could not remove session with error code %s",
+ UA_StatusCode_name(retval));
+ return retval; /* Try again next time */
+ }
+
+ /* Detach the session from the session manager and make the capacity
+ * available */
+ LIST_REMOVE(sentry, pointers);
+ UA_atomic_subUInt32(&sm->currentSessionCount, 1);
+ return UA_STATUSCODE_GOOD;
+}
+
+void UA_SessionManager_deleteMembers(UA_SessionManager *sm) {
+ session_list_entry *current, *temp;
+ LIST_FOREACH_SAFE(current, &sm->sessions, pointers, temp) {
+ removeSession(sm, current);
+ }
+}
+
+void
+UA_SessionManager_cleanupTimedOut(UA_SessionManager *sm,
+ UA_DateTime nowMonotonic) {
+ session_list_entry *sentry, *temp;
+ LIST_FOREACH_SAFE(sentry, &sm->sessions, pointers, temp) {
+ /* Session has timed out? */
+ if(sentry->session.validTill >= nowMonotonic)
+ continue;
+ UA_LOG_INFO_SESSION(sm->server->config.logger, &sentry->session,
+ "Session has timed out");
+ sm->server->config.accessControl.closeSession(sm->server,
+ &sm->server->config.accessControl,
+ &sentry->session.sessionId,
+ sentry->session.sessionHandle);
+ removeSession(sm, sentry);
+ }
+}
+
+UA_Session *
+UA_SessionManager_getSessionByToken(UA_SessionManager *sm, const UA_NodeId *token) {
+ session_list_entry *current = NULL;
+ LIST_FOREACH(current, &sm->sessions, pointers) {
+ /* Token does not match */
+ if(!UA_NodeId_equal(&current->session.header.authenticationToken, token))
+ continue;
+
+ /* Session has timed out */
+ if(UA_DateTime_nowMonotonic() > current->session.validTill) {
+ UA_LOG_INFO_SESSION(sm->server->config.logger, &current->session,
+ "Client tries to use a session that has timed out");
+ return NULL;
+ }
+
+ /* Ok, return */
+ return &current->session;
+ }
+
+ /* Session not found */
+ UA_LOG_INFO(sm->server->config.logger, UA_LOGCATEGORY_SESSION,
+ "Try to use Session with token " UA_PRINTF_GUID_FORMAT " but is not found",
+ UA_PRINTF_GUID_DATA(token->identifier.guid));
+ return NULL;
+}
+
+UA_Session *
+UA_SessionManager_getSessionById(UA_SessionManager *sm, const UA_NodeId *sessionId) {
+ session_list_entry *current = NULL;
+ LIST_FOREACH(current, &sm->sessions, pointers) {
+ /* Token does not match */
+ if(!UA_NodeId_equal(&current->session.sessionId, sessionId))
+ continue;
+
+ /* Session has timed out */
+ if(UA_DateTime_nowMonotonic() > current->session.validTill) {
+ UA_LOG_INFO_SESSION(sm->server->config.logger, &current->session,
+ "Client tries to use a session that has timed out");
+ return NULL;
+ }
+
+ /* Ok, return */
+ return &current->session;
+ }
+
+ /* Session not found */
+ UA_LOG_INFO(sm->server->config.logger, UA_LOGCATEGORY_SESSION,
+ "Try to use Session with identifier " UA_PRINTF_GUID_FORMAT " but is not found",
+ UA_PRINTF_GUID_DATA(sessionId->identifier.guid));
+ return NULL;
+}
+
+/* Creates and adds a session. But it is not yet attached to a secure channel. */
+UA_StatusCode
+UA_SessionManager_createSession(UA_SessionManager *sm, UA_SecureChannel *channel,
+ const UA_CreateSessionRequest *request, UA_Session **session) {
+ if(sm->currentSessionCount >= sm->server->config.maxSessions)
+ return UA_STATUSCODE_BADTOOMANYSESSIONS;
+
+ session_list_entry *newentry = (session_list_entry *)UA_malloc(sizeof(session_list_entry));
+ if(!newentry)
+ return UA_STATUSCODE_BADOUTOFMEMORY;
+
+ UA_atomic_addUInt32(&sm->currentSessionCount, 1);
+ 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());
+
+ if(request->requestedSessionTimeout <= sm->server->config.maxSessionTimeout &&
+ request->requestedSessionTimeout > 0)
+ newentry->session.timeout = request->requestedSessionTimeout;
+ else
+ newentry->session.timeout = sm->server->config.maxSessionTimeout;
+
+ UA_Session_updateLifetime(&newentry->session);
+ LIST_INSERT_HEAD(&sm->sessions, newentry, pointers);
+ *session = &newentry->session;
+ return UA_STATUSCODE_GOOD;
+}
+
+UA_StatusCode
+UA_SessionManager_removeSession(UA_SessionManager *sm, const UA_NodeId *token) {
+ session_list_entry *current;
+ LIST_FOREACH(current, &sm->sessions, pointers) {
+ if(UA_NodeId_equal(&current->session.header.authenticationToken, token))
+ break;
+ }
+ if(!current)
+ return UA_STATUSCODE_BADSESSIONIDINVALID;
+ return removeSession(sm, current);
+}
+
+/*********************************** amalgamated original file "/home/jvoe/open62541/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
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * Copyright 2015-2017 (c) Julius Pfrommer, Fraunhofer IOSB
+ * Copyright 2015 (c) Chris Iatrou
+ * Copyright 2015-2016 (c) Sten Grüner
+ * Copyright 2017-2018 (c) Thomas Stalder, Blue Time Concept SA
+ * Copyright 2015 (c) Joakim L. Gilje
+ * Copyright 2016-2017 (c) Florian Palm
+ * Copyright 2015-2016 (c) Oleksiy Vasylyev
+ * Copyright 2017 (c) frax2222
+ * Copyright 2017 (c) Stefan Profanter, fortiss GmbH
+ * Copyright 2017 (c) Mattias Bornhager
+ * Copyright 2018 (c) Hilscher Gesellschaft für Systemautomation mbH (Author: Martin Lang)
+ */
+
+
+#ifdef UA_ENABLE_SUBSCRIPTIONS /* conditional compilation */
+
+UA_Subscription *
+UA_Subscription_new(UA_Session *session, UA_UInt32 subscriptionId) {
+ /* Allocate the memory */
+ 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 */
+ /* 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) {
+ Subscription_unregisterPublishCallback(server, sub);
+
+ /* Delete monitored Items */
+ UA_MonitoredItem *mon, *tmp_mon;
+ LIST_FOREACH_SAFE(mon, &sub->monitoredItems, listEntry, tmp_mon) {
+ UA_LOG_INFO_SESSION(server->config.logger, sub->session,
+ "Subscription %u | MonitoredItem %i | "
+ "Deleted the MonitoredItem", sub->subscriptionId,
+ mon->monitoredItemId);
+ MonitoredItem_delete(server, mon);
+ }
+ sub->monitoredItemsSize = 0;
+
+ /* Delete Retransmission Queue */
+ UA_NotificationMessageEntry *nme, *nme_tmp;
+ TAILQ_FOREACH_SAFE(nme, &sub->retransmissionQueue, listEntry, nme_tmp) {
+ TAILQ_REMOVE(&sub->retransmissionQueue, nme, listEntry);
+ UA_NotificationMessage_deleteMembers(&nme->message);
+ UA_free(nme);
+ --sub->session->totalRetransmissionQueueSize;
+ --sub->retransmissionQueueSize;
+ }
+ UA_assert(sub->retransmissionQueueSize == 0);
+
+ UA_LOG_INFO_SESSION(server->config.logger, sub->session,
+ "Subscription %u | Deleted the Subscription",
+ sub->subscriptionId);
+}
+
+UA_MonitoredItem *
+UA_Subscription_getMonitoredItem(UA_Subscription *sub, UA_UInt32 monitoredItemId) {
+ UA_MonitoredItem *mon;
+ LIST_FOREACH(mon, &sub->monitoredItems, listEntry) {
+ if(mon->monitoredItemId == monitoredItemId)
+ break;
+ }
+ return mon;
+}
+
+UA_StatusCode
+UA_Subscription_deleteMonitoredItem(UA_Server *server, UA_Subscription *sub,
+ UA_UInt32 monitoredItemId) {
+ /* 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 %u | MonitoredItem %i | "
+ "Delete the MonitoredItem", sub->subscriptionId,
+ mon->monitoredItemId);
+
+ /* Remove the MonitoredItem */
+ MonitoredItem_delete(server, mon);
+ sub->monitoredItemsSize--;
+ return UA_STATUSCODE_GOOD;
+}
+
+void
+UA_Subscription_addMonitoredItem(UA_Subscription *sub, UA_MonitoredItem *newMon) {
+ sub->monitoredItemsSize++;
+ LIST_INSERT_HEAD(&sub->monitoredItems, newMon, listEntry);
+}
+
+static void
+removeOldestRetransmissionMessage(UA_Session *session) {
+ UA_NotificationMessageEntry *oldestEntry = NULL;
+ UA_Subscription *oldestSub = NULL;
+
+ UA_Subscription *sub;
+ LIST_FOREACH(sub, &session->serverSubscriptions, listEntry) {
+ UA_NotificationMessageEntry *first =
+ TAILQ_LAST(&sub->retransmissionQueue, ListOfNotificationMessages);
+ if(!first)
+ continue;
+ if(!oldestEntry || oldestEntry->message.publishTime > first->message.publishTime) {
+ oldestEntry = first;
+ oldestSub = sub;
+ }
+ }
+ UA_assert(oldestEntry);
+ UA_assert(oldestSub);
+
+ TAILQ_REMOVE(&oldestSub->retransmissionQueue, oldestEntry, listEntry);
+ UA_NotificationMessage_deleteMembers(&oldestEntry->message);
+ UA_free(oldestEntry);
+ --session->totalRetransmissionQueueSize;
+ --oldestSub->retransmissionQueueSize;
+}
+
+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 %u | "
+ "Retransmission queue overflow", sub->subscriptionId);
+ removeOldestRetransmissionMessage(sub->session);
+ }
+
+ /* Add entry */
+ TAILQ_INSERT_TAIL(&sub->retransmissionQueue, entry, listEntry);
+ ++sub->session->totalRetransmissionQueueSize;
+ ++sub->retransmissionQueueSize;
+}
+
+UA_StatusCode
+UA_Subscription_removeRetransmissionMessage(UA_Subscription *sub, UA_UInt32 sequenceNumber) {
+ /* Find the retransmission message */
+ UA_NotificationMessageEntry *entry;
+ TAILQ_FOREACH(entry, &sub->retransmissionQueue, listEntry) {
+ if(entry->message.sequenceNumber == sequenceNumber)
+ break;
+ }
+ if(!entry)
+ return UA_STATUSCODE_BADSEQUENCENUMBERUNKNOWN;
+
+ /* Remove the retransmission message */
+ TAILQ_REMOVE(&sub->retransmissionQueue, entry, listEntry);
+ --sub->session->totalRetransmissionQueueSize;
+ --sub->retransmissionQueueSize;
+ UA_NotificationMessage_deleteMembers(&entry->message);
+ UA_free(entry);
+ return UA_STATUSCODE_GOOD;
+}
+
+/* Iterate over the monitoreditems of the subscription, starting at mon, and
+ * move notifications into the response. */
+static void
+moveNotificationsFromMonitoredItems(UA_Subscription *sub, UA_MonitoredItemNotification *mins,
+ size_t minsSize) {
+ size_t pos = 0;
+ UA_Notification *notification, *notification_tmp;
+ TAILQ_FOREACH_SAFE(notification, &sub->notificationQueue, globalEntry, notification_tmp) {
+ if(pos >= minsSize)
+ return;
+
+ UA_MonitoredItem *mon = notification->mon;
+
+ /* Remove the notification from the queues */
+ TAILQ_REMOVE(&sub->notificationQueue, notification, globalEntry);
+ TAILQ_REMOVE(&mon->queue, notification, listEntry);
+ --mon->queueSize;
+ --sub->notificationQueueSize;
+
+ /* Move the content to the response */
+ UA_MonitoredItemNotification *min = &mins[pos];
+ min->clientHandle = mon->clientHandle;
+ if(mon->monitoredItemType == UA_MONITOREDITEMTYPE_CHANGENOTIFY) {
+ min->value = notification->data.value;
+ } else {
+ /* TODO implementation for events */
+ }
+ UA_free(notification);
+ ++pos;
+ }
+}
+
+static UA_StatusCode
+prepareNotificationMessage(UA_Subscription *sub, UA_NotificationMessage *message,
+ size_t notifications) {
+ /* Array of ExtensionObject to hold different kinds of notifications
+ * (currently only DataChangeNotifications) */
+ message->notificationData = UA_ExtensionObject_new();
+ if(!message->notificationData)
+ return UA_STATUSCODE_BADOUTOFMEMORY;
+ message->notificationDataSize = 1;
+
+ /* Allocate Notification */
+ UA_DataChangeNotification *dcn = UA_DataChangeNotification_new();
+ if(!dcn) {
+ UA_NotificationMessage_deleteMembers(message);
+ return UA_STATUSCODE_BADOUTOFMEMORY;
+ }
+ UA_ExtensionObject *data = message->notificationData;
+ data->encoding = UA_EXTENSIONOBJECT_DECODED;
+ data->content.decoded.data = dcn;
+ data->content.decoded.type = &UA_TYPES[UA_TYPES_DATACHANGENOTIFICATION];
+
+ /* Allocate array of notifications */
+ dcn->monitoredItems = (UA_MonitoredItemNotification *)
+ UA_Array_new(notifications,
+ &UA_TYPES[UA_TYPES_MONITOREDITEMNOTIFICATION]);
+ if(!dcn->monitoredItems) {
+ UA_NotificationMessage_deleteMembers(message);
+ return UA_STATUSCODE_BADOUTOFMEMORY;
+ }
+ dcn->monitoredItemsSize = notifications;
+
+ /* Move notifications into the response .. the point of no return */
+
+ moveNotificationsFromMonitoredItems(sub, dcn->monitoredItems, notifications);
+
+ return UA_STATUSCODE_GOOD;
+}
+
+/* According to OPC Unified Architecture, Part 4 5.13.1.1 i) The value 0 is
+ * never used for the sequence number */
+static UA_UInt32
+UA_Subscription_nextSequenceNumber(UA_UInt32 sequenceNumber) {
+ UA_UInt32 nextSequenceNumber = sequenceNumber + 1;
+ if(nextSequenceNumber == 0)
+ nextSequenceNumber = 1;
+ return nextSequenceNumber;
+}
+
+static void
+publishCallback(UA_Server *server, UA_Subscription *sub) {
+ sub->readyNotifications = sub->notificationQueueSize;
+ UA_Subscription_publish(server, sub);
+}
+
+void
+UA_Subscription_publish(UA_Server *server, UA_Subscription *sub) {
+ UA_LOG_DEBUG_SESSION(server->config.logger, sub->session, "Subscription %u | "
+ "Publish Callback", sub->subscriptionId);
+ /* Dequeue a response */
+ UA_PublishResponseEntry *pre = UA_Session_dequeuePublishReq(sub->session);
+ if(pre) {
+ sub->currentLifetimeCount = 0; /* Reset the LifetimeCounter */
+ } else {
+ UA_LOG_DEBUG_SESSION(server->config.logger, sub->session,
+ "Subscription %u | The publish queue is empty",
+ sub->subscriptionId);
+ ++sub->currentLifetimeCount;
+
+ if(sub->currentLifetimeCount > sub->lifeTimeCount) {
+ UA_LOG_DEBUG_SESSION(server->config.logger, sub->session,
+ "Subscription %u | End of lifetime "
+ "for subscription", sub->subscriptionId);
+ UA_Session_deleteSubscription(server, sub->session, sub->subscriptionId);
+ /* TODO: send a StatusChangeNotification with Bad_Timeout */
+ return;
+ }
+ }
+
+ if (sub->readyNotifications > sub->notificationQueueSize)
+ sub->readyNotifications = sub->notificationQueueSize;
+
+ /* Count the available notifications */
+ UA_UInt32 notifications = sub->readyNotifications;
+ if(!sub->publishingEnabled)
+ notifications = 0;
+
+ UA_Boolean moreNotifications = false;
+ if(notifications > sub->notificationsPerPublish) {
+ notifications = sub->notificationsPerPublish;
+ moreNotifications = true;
+ }
+
+ /* Return if no notifications and no keepalive */
+ if(notifications == 0) {
+ ++sub->currentKeepAliveCount;
+ if(sub->currentKeepAliveCount < sub->maxKeepAliveCount) {
+ if(pre)
+ UA_Session_queuePublishReq(sub->session, pre, true); /* Re-enqueue */
+ return;
+ }
+ UA_LOG_DEBUG_SESSION(server->config.logger, sub->session,
+ "Subscription %u | Sending a KeepAlive",
+ sub->subscriptionId);
+ }
+
+ /* We want to send a response. Is it possible? */
+ UA_SecureChannel *channel = sub->session->header.channel;
+ if(!channel || !pre) {
+ UA_LOG_DEBUG_SESSION(server->config.logger, sub->session,
+ "Subscription %u | Want to send a publish response but can't. "
+ "The subscription is late.", sub->subscriptionId);
+ sub->state = UA_SUBSCRIPTIONSTATE_LATE;
+ if(pre)
+ UA_Session_queuePublishReq(sub->session, pre, true); /* Re-enqueue */
+ return;
+ }
+
+ /* Prepare the response */
+ UA_PublishResponse *response = &pre->response;
+ UA_NotificationMessage *message = &response->notificationMessage;
+ UA_NotificationMessageEntry *retransmission = NULL;
+ if(notifications > 0) {
+ /* Allocate the retransmission entry */
+ retransmission = (UA_NotificationMessageEntry*)UA_malloc(sizeof(UA_NotificationMessageEntry));
+ if(!retransmission) {
+ UA_LOG_WARNING_SESSION(server->config.logger, sub->session,
+ "Subscription %u | Could not allocate memory for retransmission. "
+ "The subscription is late.", sub->subscriptionId);
+ sub->state = UA_SUBSCRIPTIONSTATE_LATE;
+ UA_Session_queuePublishReq(sub->session, pre, true); /* Re-enqueue */
+ return;
+ }
+
+ /* Prepare the response */
+ UA_StatusCode retval = prepareNotificationMessage(sub, message, notifications);
+ if(retval != UA_STATUSCODE_GOOD) {
+ UA_LOG_WARNING_SESSION(server->config.logger, sub->session,
+ "Subscription %u | Could not prepare the notification message. "
+ "The subscription is late.", sub->subscriptionId);
+ UA_free(retransmission);
+ sub->state = UA_SUBSCRIPTIONSTATE_LATE;
+ UA_Session_queuePublishReq(sub->session, pre, true); /* Re-enqueue */
+ return;
+ }
+ }
+
+ /* <-- The point of no return --> */
+
+ /* Adjust the number of ready notifications */
+ UA_assert(sub->readyNotifications >= notifications);
+ sub->readyNotifications -= notifications;
+
+ /* Set up the response */
+ response->responseHeader.timestamp = UA_DateTime_now();
+ response->subscriptionId = sub->subscriptionId;
+ 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. */
+ message->sequenceNumber = sub->nextSequenceNumber;
+
+ if(notifications > 0) {
+ /* 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. */
+ 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);
+ }
+
+ /* 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;
+ }
+ }
+
+ /* Send the response */
+ UA_LOG_DEBUG_SESSION(server->config.logger, sub->session,
+ "Subscription %u | Sending out a publish response "
+ "with %u notifications", sub->subscriptionId,
+ (UA_UInt32)notifications);
+ UA_SecureChannel_sendSymmetricMessage(sub->session->header.channel, pre->requestId,
+ UA_MESSAGETYPE_MSG, response,
+ &UA_TYPES[UA_TYPES_PUBLISHRESPONSE]);
+
+ /* Reset subscription state to normal */
+ sub->state = UA_SUBSCRIPTIONSTATE_NORMAL;
+ sub->currentKeepAliveCount = 0;
+
+ /* Free the response */
+ UA_Array_delete(response->results, response->resultsSize, &UA_TYPES[UA_TYPES_UINT32]);
+ UA_free(pre); /* No need for UA_PublishResponse_deleteMembers */
+
+ /* 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_LOG_DEBUG_SESSION(server->config.logger, session, "Reached number of publish request limit");
+
+ /* Dequeue a response */
+ UA_PublishResponseEntry *pre = UA_Session_dequeuePublishReq(session);
+
+ /* Cannot publish without a response */
+ if(!pre) {
+ UA_LOG_FATAL_SESSION(server->config.logger, session, "No publish requests available");
+ return false;
+ }
+
+ /* <-- The point of no return --> */
+
+ UA_PublishResponse *response = &pre->response;
+ UA_NotificationMessage *message = &response->notificationMessage;
+
+ /* Set up the response. Note that this response has no related subscription id */
+ response->responseHeader.timestamp = UA_DateTime_now();
+ response->responseHeader.serviceResult = UA_STATUSCODE_BADTOOMANYPUBLISHREQUESTS;
+ response->subscriptionId = 0;
+ response->moreNotifications = false;
+ message->publishTime = response->responseHeader.timestamp;
+ message->sequenceNumber = 0;
+ response->availableSequenceNumbersSize = 0;
+
+ /* Send the response */
+ UA_LOG_DEBUG_SESSION(server->config.logger, session,
+ "Sending out a publish response triggered by too many publish requests");
+ UA_SecureChannel_sendSymmetricMessage(session->header.channel, pre->requestId,
+ UA_MESSAGETYPE_MSG, response, &UA_TYPES[UA_TYPES_PUBLISHRESPONSE]);
+
+ /* Free the response */
+ UA_Array_delete(response->results, response->resultsSize, &UA_TYPES[UA_TYPES_UINT32]);
+ UA_free(pre); /* no need for UA_PublishResponse_deleteMembers */
+
+ return true;
+}
+
+UA_StatusCode
+Subscription_registerPublishCallback(UA_Server *server, UA_Subscription *sub) {
+ UA_LOG_DEBUG_SESSION(server->config.logger, sub->session,
+ "Subscription %u | Register subscription "
+ "publishing callback", sub->subscriptionId);
+
+ if(sub->publishCallbackIsRegistered)
+ return UA_STATUSCODE_GOOD;
+
+ UA_StatusCode retval =
+ UA_Server_addRepeatedCallback(server, (UA_ServerCallback)publishCallback,
+ sub, (UA_UInt32)sub->publishingInterval, &sub->publishCallbackId);
+ if(retval != UA_STATUSCODE_GOOD)
+ return retval;
+
+ sub->publishCallbackIsRegistered = true;
+ return UA_STATUSCODE_GOOD;
+}
+
+UA_StatusCode
+Subscription_unregisterPublishCallback(UA_Server *server, UA_Subscription *sub) {
+ UA_LOG_DEBUG_SESSION(server->config.logger, sub->session, "Subscription %u | "
+ "Unregister subscription publishing callback", sub->subscriptionId);
+
+ if(!sub->publishCallbackIsRegistered)
+ return UA_STATUSCODE_GOOD;
+
+ UA_StatusCode retval = UA_Server_removeRepeatedCallback(server, sub->publishCallbackId);
+ if(retval != UA_STATUSCODE_GOOD)
+ return retval;
+
+ sub->publishCallbackIsRegistered = false;
+ return UA_STATUSCODE_GOOD;
+}
+
+/* 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();
+ UA_SecureChannel_sendSymmetricMessage(session->header.channel, pre->requestId, UA_MESSAGETYPE_MSG,
+ response, &UA_TYPES[UA_TYPES_PUBLISHRESPONSE]);
+ UA_PublishResponse_deleteMembers(response);
+ UA_free(pre);
+ }
+}
+
+#endif /* UA_ENABLE_SUBSCRIPTIONS */
+
+/*********************************** amalgamated original file "/home/jvoe/open62541/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/.
+ *
+ * Copyright 2017 (c) Julius Pfrommer, Fraunhofer IOSB
+ * Copyright 2017 (c) Stefan Profanter, fortiss GmbH
+ * Copyright 2018 (c) Thomas Stalder, Blue Time Concept SA
+ */
+
+
+#ifdef UA_ENABLE_SUBSCRIPTIONS /* conditional compilation */
+
+#define UA_VALUENCODING_MAXSTACK 512
+
+UA_MonitoredItem *
+UA_MonitoredItem_new(UA_MonitoredItemType monType) {
+ /* Allocate the memory */
+ UA_MonitoredItem *newItem =
+ (UA_MonitoredItem *) UA_calloc(1, sizeof(UA_MonitoredItem));
+ if(!newItem)
+ return NULL;
+
+ /* Remaining members are covered by calloc zeroing out the memory */
+ newItem->monitoredItemType = monType; /* currently hardcoded */
+ newItem->timestampsToReturn = UA_TIMESTAMPSTORETURN_SOURCE;
+ TAILQ_INIT(&newItem->queue);
+ return newItem;
+}
+
+void
+MonitoredItem_delete(UA_Server *server, UA_MonitoredItem *monitoredItem) {
+ UA_Subscription *sub = monitoredItem->subscription;
+
+ if(monitoredItem->monitoredItemType == UA_MONITOREDITEMTYPE_CHANGENOTIFY) {
+ /* Remove the sampling callback */
+ MonitoredItem_unregisterSampleCallback(server, monitoredItem);
+
+ /* Clear the queued notifications */
+ UA_Notification *notification, *notification_tmp;
+ TAILQ_FOREACH_SAFE(notification, &monitoredItem->queue, listEntry, notification_tmp) {
+ /* Remove the item from the queues */
+ TAILQ_REMOVE(&monitoredItem->queue, notification, listEntry);
+ TAILQ_REMOVE(&sub->notificationQueue, notification, globalEntry);
+ --sub->notificationQueueSize;
+
+ UA_DataValue_deleteMembers(&notification->data.value);
+ UA_free(notification);
+ }
+ monitoredItem->queueSize = 0;
+ } else {
+ /* TODO: Access val data.event */
+ UA_LOG_ERROR(server->config.logger, UA_LOGCATEGORY_SERVER,
+ "MonitoredItemTypes other than ChangeNotify are not supported yet");
+ }
+
+ /* Remove the monitored item */
+ if(monitoredItem->listEntry.le_prev != NULL)
+ LIST_REMOVE(monitoredItem, listEntry);
+ UA_String_deleteMembers(&monitoredItem->indexRange);
+ UA_ByteString_deleteMembers(&monitoredItem->lastSampledValue);
+ UA_Variant_deleteMembers(&monitoredItem->lastValue);
+ UA_NodeId_deleteMembers(&monitoredItem->monitoredNodeId);
+ UA_Server_delayedFree(server, monitoredItem);
+}
+
+void MonitoredItem_ensureQueueSpace(UA_MonitoredItem *mon) {
+ if(mon->queueSize <= mon->maxQueueSize)
+ return;
+
+ /* Remove notifications until the queue size is reached */
+ UA_Subscription *sub = mon->subscription;
+ while(mon->queueSize > mon->maxQueueSize) {
+ UA_assert(mon->queueSize >= 2); /* At least two Notifications in the queue */
+
+ /* Make sure that the MonitoredItem does not lose its place in the
+ * global queue when notifications are removed. Otherwise the
+ * MonitoredItem can "starve" itself by putting new notifications always
+ * at the end of the global queue and removing the old ones.
+ *
+ * - If the oldest notification is removed, put the second oldest
+ * notification right behind it.
+ * - If the newest notification is removed, put the new notification
+ * right behind it. */
+
+ UA_Notification *del; /* The notification that will be deleted */
+ UA_Notification *after_del; /* The notification to keep and move after del */
+ if(mon->discardOldest) {
+ /* Remove the oldest */
+ del = TAILQ_FIRST(&mon->queue);
+ after_del = TAILQ_NEXT(del, listEntry);
+ } else {
+ /* Remove the second newest (to keep the up-to-date notification) */
+ after_del = TAILQ_LAST(&mon->queue, NotificationQueue);
+ del = TAILQ_PREV(after_del, NotificationQueue, listEntry);
+ }
+
+ /* Move after_del right after del in the global queue */
+ TAILQ_REMOVE(&sub->notificationQueue, after_del, globalEntry);
+ TAILQ_INSERT_AFTER(&sub->notificationQueue, del, after_del, globalEntry);
+
+ /* Remove the notification from the queues */
+ TAILQ_REMOVE(&mon->queue, del, listEntry);
+ TAILQ_REMOVE(&sub->notificationQueue, del, globalEntry);
+ --mon->queueSize;
+ --sub->notificationQueueSize;
+
+ /* Free the notification */
+ if(mon->monitoredItemType == UA_MONITOREDITEMTYPE_CHANGENOTIFY) {
+ UA_DataValue_deleteMembers(&del->data.value);
+ } else {
+ /* TODO: event implemantation */
+ }
+
+ /* Work around a false positive in clang analyzer */
+#ifndef __clang_analyzer__
+ UA_free(del);
+#endif
+ }
+
+ if(mon->monitoredItemType == UA_MONITOREDITEMTYPE_CHANGENOTIFY) {
+ /* Get the element that carries the infobits */
+ UA_Notification *notification = NULL;
+ if(mon->discardOldest)
+ notification = TAILQ_FIRST(&mon->queue);
+ else
+ notification = TAILQ_LAST(&mon->queue, NotificationQueue);
+ UA_assert(notification);
+
+ if(mon->maxQueueSize > 1) {
+ /* Add the infobits either to the newest or the new last entry */
+ notification->data.value.hasStatus = true;
+ notification->data.value.status |= (UA_STATUSCODE_INFOTYPE_DATAVALUE |
+ UA_STATUSCODE_INFOBITS_OVERFLOW);
+ } else {
+ /* If the queue size is reduced to one, remove the infobits */
+ notification->data.value.status &= ~(UA_StatusCode)(UA_STATUSCODE_INFOTYPE_DATAVALUE |
+ UA_STATUSCODE_INFOBITS_OVERFLOW);
+ }
+ }
+
+ /* TODO: Infobits for Events? */
+}
+
+#define ABS_SUBTRACT_TYPE_INDEPENDENT(a,b) ((a)>(b)?(a)-(b):(b)-(a))
+
+static UA_INLINE UA_Boolean
+outOfDeadBand(const void *data1, const void *data2, const size_t index, const UA_DataType *type, const UA_Double deadbandValue) {
+ if(type == &UA_TYPES[UA_TYPES_BOOLEAN]) {
+ if(ABS_SUBTRACT_TYPE_INDEPENDENT(((const UA_Boolean*)data1)[index], ((const UA_Boolean*)data2)[index]) <= deadbandValue)
+ return false;
+ } else
+ if (type == &UA_TYPES[UA_TYPES_SBYTE]) {
+ if (ABS_SUBTRACT_TYPE_INDEPENDENT(((const UA_SByte*)data1)[index], ((const UA_SByte*)data2)[index]) <= deadbandValue)
+ return false;
+ } else
+ if (type == &UA_TYPES[UA_TYPES_BYTE]) {
+ if (ABS_SUBTRACT_TYPE_INDEPENDENT(((const UA_Byte*)data1)[index], ((const UA_Byte*)data2)[index]) <= deadbandValue)
+ return false;
+ } else
+ if (type == &UA_TYPES[UA_TYPES_INT16]) {
+ if (ABS_SUBTRACT_TYPE_INDEPENDENT(((const UA_Int16*)data1)[index], ((const UA_Int16*)data2)[index]) <= deadbandValue)
+ return false;
+ } else
+ if (type == &UA_TYPES[UA_TYPES_UINT16]) {
+ if (ABS_SUBTRACT_TYPE_INDEPENDENT(((const UA_UInt16*)data1)[index], ((const UA_UInt16*)data2)[index]) <= deadbandValue)
+ return false;
+ } else
+ if (type == &UA_TYPES[UA_TYPES_INT32]) {
+ if (ABS_SUBTRACT_TYPE_INDEPENDENT(((const UA_Int32*)data1)[index], ((const UA_Int32*)data2)[index]) <= deadbandValue)
+ return false;
+ } else
+ if (type == &UA_TYPES[UA_TYPES_UINT32]) {
+ if (ABS_SUBTRACT_TYPE_INDEPENDENT(((const UA_UInt32*)data1)[index], ((const UA_UInt32*)data2)[index]) <= deadbandValue)
+ return false;
+ } else
+ if (type == &UA_TYPES[UA_TYPES_INT64]) {
+ if (ABS_SUBTRACT_TYPE_INDEPENDENT(((const UA_Int64*)data1)[index], ((const UA_Int64*)data2)[index]) <= deadbandValue)
+ return false;
+ } else
+ if (type == &UA_TYPES[UA_TYPES_UINT64]) {
+ if (ABS_SUBTRACT_TYPE_INDEPENDENT(((const UA_UInt64*)data1)[index], ((const UA_UInt64*)data2)[index]) <= deadbandValue)
+ return false;
+ } else
+ if (type == &UA_TYPES[UA_TYPES_FLOAT]) {
+ if (ABS_SUBTRACT_TYPE_INDEPENDENT(((const UA_Float*)data1)[index], ((const UA_Float*)data2)[index]) <= deadbandValue)
+ return false;
+ } else
+ if (type == &UA_TYPES[UA_TYPES_DOUBLE]) {
+ if (ABS_SUBTRACT_TYPE_INDEPENDENT(((const UA_Double*)data1)[index], ((const UA_Double*)data2)[index]) <= deadbandValue)
+ return false;
+ }
+ return true;
+}
+
+static UA_INLINE UA_Boolean
+updateNeededForFilteredValue(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;
+ }
+ if (UA_Variant_isScalar(value)) {
+ return outOfDeadBand(value->data, oldValue->data, 0, value->type, deadbandValue);
+ } else {
+ for (size_t i = 0; i < value->arrayLength; ++i) {
+ if (outOfDeadBand(value->data, oldValue->data, i, value->type, deadbandValue))
+ return true;
+ }
+ }
+ return false;
+}
+
+/* Errors are returned as no change detected */
+static UA_Boolean
+detectValueChangeWithFilter(UA_MonitoredItem *mon, UA_DataValue *value,
+ UA_ByteString *encoding) {
+ if (isDataTypeNumeric(value->value.type)
+ && (mon->filter.trigger == UA_DATACHANGETRIGGER_STATUSVALUE
+ || mon->filter.trigger == UA_DATACHANGETRIGGER_STATUSVALUETIMESTAMP)) {
+ if (mon->filter.deadbandType == UA_DEADBANDTYPE_ABSOLUTE) {
+ if (!updateNeededForFilteredValue(&value->value, &mon->lastValue, mon->filter.deadbandValue))
+ return false;
+ } /*else if (mon->filter.deadbandType == UA_DEADBANDTYPE_PERCENT) {
+ // TODO where do this EURange come from ?
+ UA_Double deadbandValue = fabs(mon->filter.deadbandValue * (EURange.high-EURange.low));
+ if (!updateNeededForFilteredValue(value->value, mon->lastValue, deadbandValue))
+ return false;
+ }*/
+ }
+
+ /* Encode the data for comparison */
+ size_t binsize = UA_calcSizeBinary(value, &UA_TYPES[UA_TYPES_DATAVALUE]);
+ if(binsize == 0)
+ return false;
+
+ /* Allocate buffer on the heap if necessary */
+ if(binsize > UA_VALUENCODING_MAXSTACK &&
+ UA_ByteString_allocBuffer(encoding, binsize) != UA_STATUSCODE_GOOD)
+ return false;
+
+ /* Encode the value */
+ UA_Byte *bufPos = encoding->data;
+ const UA_Byte *bufEnd = &encoding->data[encoding->length];
+ UA_StatusCode retval = UA_encodeBinary(value, &UA_TYPES[UA_TYPES_DATAVALUE],
+ &bufPos, &bufEnd, NULL, NULL);
+ if(retval != UA_STATUSCODE_GOOD)
+ return false;
+
+ /* The value has changed */
+ encoding->length = (uintptr_t)bufPos - (uintptr_t)encoding->data;
+ return !mon->lastSampledValue.data || !UA_String_equal(encoding, &mon->lastSampledValue);
+}
+
+/* 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_Boolean
+detectValueChange(UA_MonitoredItem *mon, UA_DataValue *value, UA_ByteString *encoding) {
+ /* Apply Filter */
+ UA_Boolean hasValue = value->hasValue;
+ if(mon->filter.trigger == UA_DATACHANGETRIGGER_STATUS)
+ value->hasValue = false;
+
+ UA_Boolean hasServerTimestamp = value->hasServerTimestamp;
+ UA_Boolean hasServerPicoseconds = value->hasServerPicoseconds;
+ value->hasServerTimestamp = false;
+ value->hasServerPicoseconds = false;
+
+ UA_Boolean hasSourceTimestamp = value->hasSourceTimestamp;
+ UA_Boolean hasSourcePicoseconds = value->hasSourcePicoseconds;
+ if(mon->filter.trigger < UA_DATACHANGETRIGGER_STATUSVALUETIMESTAMP) {
+ value->hasSourceTimestamp = false;
+ value->hasSourcePicoseconds = false;
+ }
+
+ /* Detect the Value Change */
+ UA_Boolean res = detectValueChangeWithFilter(mon, value, encoding);
+
+ /* Reset the filter */
+ value->hasValue = hasValue;
+ value->hasServerTimestamp = hasServerTimestamp;
+ value->hasServerPicoseconds = hasServerPicoseconds;
+ value->hasSourceTimestamp = hasSourceTimestamp;
+ value->hasSourcePicoseconds = hasSourcePicoseconds;
+ return res;
+}
+
+/* Returns whether a new sample was created */
+static UA_Boolean
+sampleCallbackWithValue(UA_Server *server, UA_Subscription *sub,
+ UA_MonitoredItem *monitoredItem,
+ UA_DataValue *value,
+ UA_ByteString *valueEncoding) {
+ UA_assert(monitoredItem->monitoredItemType == UA_MONITOREDITEMTYPE_CHANGENOTIFY);
+ /* Store the pointer to the stack-allocated bytestring to see if a heap-allocation
+ * was necessary */
+ UA_Byte *stackValueEncoding = valueEncoding->data;
+
+ /* Has the value changed? */
+ UA_Boolean changed = detectValueChange(monitoredItem, value, valueEncoding);
+ if(!changed)
+ return false;
+
+ /* Allocate the entry for the publish queue */
+ UA_Notification *newNotification =
+ (UA_Notification *)UA_malloc(sizeof(UA_Notification));
+ if(!newNotification) {
+ UA_LOG_WARNING_SESSION(server->config.logger, sub->session,
+ "Subscription %u | MonitoredItem %i | "
+ "Item for the publishing queue could not be allocated",
+ sub->subscriptionId, monitoredItem->monitoredItemId);
+ return false;
+ }
+
+ /* Copy valueEncoding on the heap for the next comparison (if not already done) */
+ if(valueEncoding->data == stackValueEncoding) {
+ UA_ByteString cbs;
+ if(UA_ByteString_copy(valueEncoding, &cbs) != UA_STATUSCODE_GOOD) {
+ UA_LOG_WARNING_SESSION(server->config.logger, sub->session,
+ "Subscription %u | MonitoredItem %i | "
+ "ByteString to compare values could not be created",
+ sub->subscriptionId, monitoredItem->monitoredItemId);
+ UA_free(newNotification);
+ return false;
+ }
+ *valueEncoding = cbs;
+ }
+
+ /* Prepare the newQueueItem */
+ if(value->hasValue && value->value.storageType == UA_VARIANT_DATA_NODELETE) {
+ /* Make a deep copy of the value */
+ UA_StatusCode retval = UA_DataValue_copy(value, &newNotification->data.value);
+ if(retval != UA_STATUSCODE_GOOD) {
+ UA_LOG_WARNING_SESSION(server->config.logger, sub->session,
+ "Subscription %u | MonitoredItem %i | "
+ "Item for the publishing queue could not be prepared",
+ sub->subscriptionId, monitoredItem->monitoredItemId);
+ UA_free(newNotification);
+ return false;
+ }
+ } else {
+ newNotification->data.value = *value; /* Just copy the value and do not release it */
+ }
+
+ /* <-- Point of no return --> */
+
+ UA_LOG_DEBUG_SESSION(server->config.logger, sub->session,
+ "Subscription %u | MonitoredItem %u | Sampled a new value",
+ sub->subscriptionId, monitoredItem->monitoredItemId);
+
+ newNotification->mon = monitoredItem;
+
+ /* Replace the encoding for comparison */
+ UA_Variant_deleteMembers(&monitoredItem->lastValue);
+ UA_Variant_copy(&value->value, &monitoredItem->lastValue);
+ UA_ByteString_deleteMembers(&monitoredItem->lastSampledValue);
+ monitoredItem->lastSampledValue = *valueEncoding;
+
+ /* Add the notification to the end of local and global queue */
+ TAILQ_INSERT_TAIL(&monitoredItem->queue, newNotification, listEntry);
+ TAILQ_INSERT_TAIL(&sub->notificationQueue, newNotification, globalEntry);
+ ++monitoredItem->queueSize;
+ ++sub->notificationQueueSize;
+
+ /* Remove some notifications if the queue is beyond maximum capacity */
+ MonitoredItem_ensureQueueSpace(monitoredItem);
+
+ return true;
+}
+
+void
+UA_MonitoredItem_SampleCallback(UA_Server *server,
+ UA_MonitoredItem *monitoredItem) {
+ UA_Subscription *sub = monitoredItem->subscription;
+ if(monitoredItem->monitoredItemType != UA_MONITOREDITEMTYPE_CHANGENOTIFY) {
+ UA_LOG_DEBUG_SESSION(server->config.logger, sub->session,
+ "Subscription %u | MonitoredItem %i | "
+ "Not a data change notification",
+ sub->subscriptionId, monitoredItem->monitoredItemId);
+ return;
+ }
+
+ /* Read the value */
+ UA_ReadValueId rvid;
+ UA_ReadValueId_init(&rvid);
+ rvid.nodeId = monitoredItem->monitoredNodeId;
+ rvid.attributeId = monitoredItem->attributeId;
+ rvid.indexRange = monitoredItem->indexRange;
+ UA_DataValue value =
+ UA_Server_readWithSession(server, sub->session,
+ &rvid, monitoredItem->timestampsToReturn);
+
+ /* 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;
+
+ /* Create a sample and compare with the last value */
+ UA_Boolean newNotification = sampleCallbackWithValue(server, sub, monitoredItem,
+ &value, &valueEncoding);
+
+ /* Clean up */
+ if(!newNotification) {
+ if(valueEncoding.data != stackValueEncoding)
+ UA_ByteString_deleteMembers(&valueEncoding);
+ UA_DataValue_deleteMembers(&value);
+ }
+}
+
+UA_StatusCode
+MonitoredItem_registerSampleCallback(UA_Server *server, UA_MonitoredItem *mon) {
+ if(mon->sampleCallbackIsRegistered)
+ return UA_STATUSCODE_GOOD;
+ UA_StatusCode retval =
+ UA_Server_addRepeatedCallback(server, (UA_ServerCallback)UA_MonitoredItem_SampleCallback,
+ mon, (UA_UInt32)mon->samplingInterval, &mon->sampleCallbackId);
+ if(retval == UA_STATUSCODE_GOOD)
+ mon->sampleCallbackIsRegistered = true;
+ return retval;
+}
+
+UA_StatusCode
+MonitoredItem_unregisterSampleCallback(UA_Server *server, UA_MonitoredItem *mon) {
+ if(!mon->sampleCallbackIsRegistered)
+ return UA_STATUSCODE_GOOD;
+ mon->sampleCallbackIsRegistered = false;
+ return UA_Server_removeRepeatedCallback(server, mon->sampleCallbackId);
+}
+
+#endif /* UA_ENABLE_SUBSCRIPTIONS */
+
+/*********************************** amalgamated original file "/home/jvoe/open62541/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
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * Copyright 2014-2017 (c) Julius Pfrommer, Fraunhofer IOSB
+ * Copyright 2014-2017 (c) Florian Palm
+ * Copyright 2015-2016 (c) Sten Grüner
+ * Copyright 2015 (c) LEvertz
+ * Copyright 2015 (c) Chris Iatrou
+ * Copyright 2015 (c) Ecosmos
+ * Copyright 2015-2016 (c) Oleksiy Vasylyev
+ * Copyright 2017 (c) Stefan Profanter, fortiss GmbH
+ * Copyright 2016 (c) Lorenz Haas
+ * Copyright 2017 (c) pschoppe
+ * Copyright 2017 (c) Julian Grothoff
+ * Copyright 2017 (c) Henrik Norrman
+ */
+
+
+/* Target node on top of the stack */
+static UA_StatusCode
+fillReferenceDescription(UA_Server *server, const UA_Node *curr,
+ const UA_NodeReferenceKind *ref,
+ UA_UInt32 mask, UA_ReferenceDescription *descr) {
+ UA_ReferenceDescription_init(descr);
+ UA_StatusCode retval = UA_NodeId_copy(&curr->nodeId, &descr->nodeId.nodeId);
+ if(mask & UA_BROWSERESULTMASK_REFERENCETYPEID)
+ retval |= UA_NodeId_copy(&ref->referenceTypeId, &descr->referenceTypeId);
+ if(mask & UA_BROWSERESULTMASK_ISFORWARD)
+ descr->isForward = !ref->isInverse;
+ if(mask & UA_BROWSERESULTMASK_NODECLASS)
+ retval |= UA_NodeClass_copy(&curr->nodeClass, &descr->nodeClass);
+ if(mask & UA_BROWSERESULTMASK_BROWSENAME)
+ retval |= UA_QualifiedName_copy(&curr->browseName, &descr->browseName);
+ if(mask & UA_BROWSERESULTMASK_DISPLAYNAME)
+ retval |= UA_LocalizedText_copy(&curr->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(type) {
+ retval |= UA_NodeId_copy(&type->nodeId, &descr->typeDefinition.nodeId);
+ UA_Nodestore_release(server, type);
+ }
+ }
+ }
+ return retval;
+}
+
+static void
+removeCp(ContinuationPointEntry *cp, UA_Session* session) {
+ LIST_REMOVE(cp, pointers);
+ UA_ByteString_deleteMembers(&cp->identifier);
+ UA_BrowseDescription_deleteMembers(&cp->browseDescription);
+ UA_free(cp);
+ ++session->availableContinuationPoints;
+}
+
+static UA_Boolean
+relevantReference(UA_Server *server, UA_Boolean includeSubtypes,
+ const UA_NodeId *rootRef, const UA_NodeId *testRef) {
+ if(!includeSubtypes)
+ return UA_NodeId_equal(rootRef, testRef);
+
+ const UA_NodeId hasSubType = UA_NODEID_NUMERIC(0, UA_NS0ID_HASSUBTYPE);
+ return isNodeInTree(&server->config.nodestore, testRef, rootRef, &hasSubType, 1);
+}
+
+/* Returns whether the node / continuationpoint is done */
+static UA_Boolean
+browseReferences(UA_Server *server, const UA_Node *node,
+ ContinuationPointEntry *cp, UA_BrowseResult *result) {
+ UA_assert(cp != NULL);
+ const UA_BrowseDescription *descr = &cp->browseDescription;
+
+ /* If the node has no references, just return */
+ if(node->referencesSize == 0) {
+ result->referencesSize = 0;
+ return true;
+ }
+
+ /* Follow all references? */
+ UA_Boolean browseAll = UA_NodeId_isNull(&descr->referenceTypeId);
+
+ /* How many references can we return at most? */
+ size_t maxrefs = cp->maxReferences;
+ if(maxrefs == 0) {
+ if(server->config.maxReferencesPerNode != 0) {
+ maxrefs = server->config.maxReferencesPerNode;
+ } else {
+ maxrefs = UA_INT32_MAX;
+ }
+ } else {
+ if(server->config.maxReferencesPerNode != 0 && maxrefs > server->config.maxReferencesPerNode) {
+ maxrefs = server->config.maxReferencesPerNode;
+ }
+ }
+
+ /* Allocate the results array */
+ size_t refs_size = 2; /* True size of the array */
+ result->references = (UA_ReferenceDescription*)
+ UA_Array_new(refs_size, &UA_TYPES[UA_TYPES_REFERENCEDESCRIPTION]);
+ if(!result->references) {
+ result->statusCode = UA_STATUSCODE_BADOUTOFMEMORY;
+ return false;
+ }
+
+ size_t referenceKindIndex = cp->referenceKindIndex;
+ size_t targetIndex = cp->targetIndex;
+
+ /* Loop over the node's references */
+ for(; referenceKindIndex < node->referencesSize; ++referenceKindIndex) {
+ UA_NodeReferenceKind *rk = &node->references[referenceKindIndex];
+
+ /* Reference in the right direction? */
+ if(rk->isInverse && descr->browseDirection == UA_BROWSEDIRECTION_FORWARD)
+ continue;
+ if(!rk->isInverse && descr->browseDirection == UA_BROWSEDIRECTION_INVERSE)
+ continue;
+
+ /* Is the reference part of the hierarchy of references we look for? */
+ if(!browseAll && !relevantReference(server, descr->includeSubtypes,
+ &descr->referenceTypeId, &rk->referenceTypeId))
+ continue;
+
+ /* Loop over the targets */
+ for(; targetIndex < rk->targetIdsSize; ++targetIndex) {
+ /* Get the node */
+ const UA_Node *target = UA_Nodestore_get(server, &rk->targetIds[targetIndex].nodeId);
+ if(!target)
+ continue;
+
+ /* Test if the node class matches */
+ if(descr->nodeClassMask != 0 && (target->nodeClass & descr->nodeClassMask) == 0) {
+ UA_Nodestore_release(server, target);
+ continue;
+ }
+
+ /* A match! Can we return it? */
+ if(result->referencesSize >= maxrefs) {
+ /* There are references we could not return */
+ cp->referenceKindIndex = referenceKindIndex;
+ cp->targetIndex = targetIndex;
+ UA_Nodestore_release(server, target);
+ return false;
+ }
+
+ /* Make enough space in the array */
+ if(result->referencesSize >= refs_size) {
+ refs_size *= 2;
+ if(refs_size > maxrefs)
+ refs_size = maxrefs;
+ UA_ReferenceDescription *rd = (UA_ReferenceDescription*)
+ UA_realloc(result->references, sizeof(UA_ReferenceDescription) * refs_size);
+ if(!rd) {
+ result->statusCode = UA_STATUSCODE_BADOUTOFMEMORY;
+ UA_Nodestore_release(server, target);
+ goto error_recovery;
+ }
+ result->references = rd;
+ }
+
+ /* Copy the node description. Target is on top of the stack */
+ result->statusCode =
+ fillReferenceDescription(server, target, rk, descr->resultMask,
+ &result->references[result->referencesSize]);
+
+ UA_Nodestore_release(server, target);
+
+ if(result->statusCode != UA_STATUSCODE_GOOD)
+ goto error_recovery;
+
+ /* Increase the counter */
+ result->referencesSize++;
+ }
+
+ targetIndex = 0; /* Start at index 0 for the next reference kind */
+ }
+
+ /* No relevant references, return array of length zero */
+ if(result->referencesSize == 0) {
+ UA_free(result->references);
+ result->references = (UA_ReferenceDescription*)UA_EMPTY_ARRAY_SENTINEL;
+ }
+
+ /* The node is done */
+ return true;
+
+ error_recovery:
+ if(result->referencesSize == 0)
+ UA_free(result->references);
+ else
+ UA_Array_delete(result->references, result->referencesSize,
+ &UA_TYPES[UA_TYPES_REFERENCEDESCRIPTION]);
+ result->references = NULL;
+ result->referencesSize = 0;
+ return false;
+}
+
+/* Results for a single browsedescription. This is the inner loop for both
+ * Browse and BrowseNext. The ContinuationPoint contains all the data used.
+ * Including the BrowseDescription. Returns whether there are remaining
+ * references. */
+static UA_Boolean
+browseWithContinuation(UA_Server *server, UA_Session *session,
+ ContinuationPointEntry *cp, UA_BrowseResult *result) {
+ const UA_BrowseDescription *descr = &cp->browseDescription;
+
+ /* Is the browsedirection valid? */
+ if(descr->browseDirection != UA_BROWSEDIRECTION_BOTH &&
+ descr->browseDirection != UA_BROWSEDIRECTION_FORWARD &&
+ descr->browseDirection != UA_BROWSEDIRECTION_INVERSE) {
+ result->statusCode = UA_STATUSCODE_BADBROWSEDIRECTIONINVALID;
+ return true;
+ }
+
+ /* Is the reference type valid? */
+ if(!UA_NodeId_isNull(&descr->referenceTypeId)) {
+ const UA_Node *reftype = UA_Nodestore_get(server, &descr->referenceTypeId);
+ if(!reftype) {
+ result->statusCode = UA_STATUSCODE_BADREFERENCETYPEIDINVALID;
+ return true;
+ }
+
+ UA_Boolean isRef = (reftype->nodeClass == UA_NODECLASS_REFERENCETYPE);
+ UA_Nodestore_release(server, reftype);
+
+ if(!isRef) {
+ result->statusCode = UA_STATUSCODE_BADREFERENCETYPEIDINVALID;
+ return true;
+ }
+ }
+
+ const UA_Node *node = UA_Nodestore_get(server, &descr->nodeId);
+ if(!node) {
+ result->statusCode = UA_STATUSCODE_BADNODEIDUNKNOWN;
+ return true;
+ }
+
+ /* Browse the references */
+ UA_Boolean done = browseReferences(server, node, cp, result);
+ UA_Nodestore_release(server, node);
+ return done;
+}
+
+/* Start to browse with no previous cp */
+void
+Operation_Browse(UA_Server *server, UA_Session *session, UA_UInt32 *maxrefs,
+ const UA_BrowseDescription *descr, UA_BrowseResult *result) {
+ /* Stack-allocate a temporary cp */
+ UA_STACKARRAY(ContinuationPointEntry, cp, 1);
+ memset(cp, 0, sizeof(ContinuationPointEntry));
+ cp->maxReferences = *maxrefs;
+ cp->browseDescription = *descr; /* Shallow copy. Deep-copy later if we persist the cp. */
+
+ UA_Boolean done = browseWithContinuation(server, session, cp, result);
+
+ /* Exit early if done or an error occurred */
+ if(done || result->statusCode != UA_STATUSCODE_GOOD)
+ return;
+
+ /* Persist the new continuation point */
+ ContinuationPointEntry *cp2 = NULL;
+ UA_StatusCode retval = UA_STATUSCODE_GOOD;
+ if(session->availableContinuationPoints <= 0 ||
+ !(cp2 = (ContinuationPointEntry *)UA_malloc(sizeof(ContinuationPointEntry)))) {
+ retval = UA_STATUSCODE_BADNOCONTINUATIONPOINTS;
+ goto cleanup;
+ }
+ memset(cp2, 0, sizeof(ContinuationPointEntry));
+ cp2->referenceKindIndex = cp->referenceKindIndex;
+ cp2->targetIndex = cp->targetIndex;
+ cp2->maxReferences = cp->maxReferences;
+ retval = UA_BrowseDescription_copy(descr, &cp2->browseDescription);
+ if(retval != UA_STATUSCODE_GOOD)
+ goto cleanup;
+
+ /* Create a random bytestring via a Guid */
+ UA_Guid *ident = UA_Guid_new();
+ if(!ident) {
+ retval = UA_STATUSCODE_BADOUTOFMEMORY;
+ goto cleanup;
+ }
+ *ident = UA_Guid_random();
+ cp2->identifier.data = (UA_Byte*)ident;
+ cp2->identifier.length = sizeof(UA_Guid);
+
+ /* Return the cp identifier */
+ retval = UA_ByteString_copy(&cp2->identifier, &result->continuationPoint);
+ if(retval != UA_STATUSCODE_GOOD)
+ goto cleanup;
+
+ /* Attach the cp to the session */
+ LIST_INSERT_HEAD(&session->continuationPoints, cp2, pointers);
+ --session->availableContinuationPoints;
+ return;
+
+ cleanup:
+ if(cp2) {
+ UA_ByteString_deleteMembers(&cp2->identifier);
+ UA_BrowseDescription_deleteMembers(&cp2->browseDescription);
+ UA_free(cp2);
+ }
+ UA_BrowseResult_deleteMembers(result);
+ result->statusCode = retval;
+}
+
+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");
+
+ if(server->config.maxNodesPerBrowse != 0 &&
+ request->nodesToBrowseSize > server->config.maxNodesPerBrowse) {
+ response->responseHeader.serviceResult = UA_STATUSCODE_BADTOOMANYOPERATIONS;
+ return;
+ }
+
+ /* No views supported at the moment */
+ if(!UA_NodeId_isNull(&request->view.viewId)) {
+ response->responseHeader.serviceResult = UA_STATUSCODE_BADVIEWIDUNKNOWN;
+ return;
+ }
+
+ UA_UInt32 requestedMaxReferencesPerNode = request->requestedMaxReferencesPerNode;
+ response->responseHeader.serviceResult =
+ UA_Server_processServiceOperations(server, session, (UA_ServiceOperation)Operation_Browse,
+ &requestedMaxReferencesPerNode,
+ &request->nodesToBrowseSize, &UA_TYPES[UA_TYPES_BROWSEDESCRIPTION],
+ &response->resultsSize, &UA_TYPES[UA_TYPES_BROWSERESULT]);
+}
+
+UA_BrowseResult
+UA_Server_browse(UA_Server *server, UA_UInt32 maxrefs, const UA_BrowseDescription *descr) {
+ UA_BrowseResult result;
+ UA_BrowseResult_init(&result);
+ Operation_Browse(server, &server->adminSession, &maxrefs, descr, &result);
+ return result;
+}
+
+static void
+Operation_BrowseNext(UA_Server *server, UA_Session *session, UA_Boolean *releaseContinuationPoints,
+ const UA_ByteString *continuationPoint, UA_BrowseResult *result) {
+ /* Find the continuation point */
+ ContinuationPointEntry *cp;
+ LIST_FOREACH(cp, &session->continuationPoints, pointers) {
+ if(UA_ByteString_equal(&cp->identifier, continuationPoint))
+ break;
+ }
+ if(!cp) {
+ result->statusCode = UA_STATUSCODE_BADCONTINUATIONPOINTINVALID;
+ return;
+ }
+
+ /* Remove the cp */
+ if(*releaseContinuationPoints) {
+ removeCp(cp, session);
+ return;
+ }
+
+ /* Continue browsing */
+ UA_Boolean done = browseWithContinuation(server, session, cp, result);
+
+ if(done) {
+ /* Remove the cp if there are no references left */
+ removeCp(cp, session);
+ } else {
+ /* Return the cp identifier */
+ UA_StatusCode retval = UA_ByteString_copy(&cp->identifier, &result->continuationPoint);
+ if(retval != UA_STATUSCODE_GOOD) {
+ UA_BrowseResult_deleteMembers(result);
+ result->statusCode = retval;
+ }
+ }
+}
+
+void
+Service_BrowseNext(UA_Server *server, UA_Session *session,
+ const UA_BrowseNextRequest *request,
+ UA_BrowseNextResponse *response) {
+ UA_LOG_DEBUG_SESSION(server->config.logger, session,
+ "Processing BrowseNextRequest");
+ UA_Boolean releaseContinuationPoints = request->releaseContinuationPoints; /* request is const */
+ response->responseHeader.serviceResult =
+ UA_Server_processServiceOperations(server, session, (UA_ServiceOperation)Operation_BrowseNext,
+ &releaseContinuationPoints,
+ &request->continuationPointsSize, &UA_TYPES[UA_TYPES_BYTESTRING],
+ &response->resultsSize, &UA_TYPES[UA_TYPES_BROWSERESULT]);
+}
+
+UA_BrowseResult
+UA_Server_browseNext(UA_Server *server, UA_Boolean releaseContinuationPoint,
+ const UA_ByteString *continuationPoint) {
+ UA_BrowseResult result;
+ UA_BrowseResult_init(&result);
+ Operation_BrowseNext(server, &server->adminSession, &releaseContinuationPoint,
+ continuationPoint, &result);
+ return result;
+}
+
+/***********************/
+/* TranslateBrowsePath */
+/***********************/
+
+static void
+walkBrowsePathElementReferenceTargets(UA_BrowsePathResult *result, size_t *targetsSize,
+ UA_NodeId **next, size_t *nextSize, size_t *nextCount,
+ UA_UInt32 elemDepth, const UA_NodeReferenceKind *rk) {
+ /* Loop over the targets */
+ for(size_t i = 0; i < rk->targetIdsSize; i++) {
+ UA_ExpandedNodeId *targetId = &rk->targetIds[i];
+
+ /* Does the reference point to an external server? Then add to the
+ * targets with the right path depth. */
+ if(targetId->serverIndex != 0) {
+ UA_BrowsePathTarget *tempTargets =
+ (UA_BrowsePathTarget*)UA_realloc(result->targets,
+ sizeof(UA_BrowsePathTarget) * (*targetsSize) * 2);
+ if(!tempTargets) {
+ result->statusCode = UA_STATUSCODE_BADOUTOFMEMORY;
+ return;
+ }
+ result->targets = tempTargets;
+ (*targetsSize) *= 2;
+ result->statusCode = UA_ExpandedNodeId_copy(targetId,
+ &result->targets[result->targetsSize].targetId);
+ result->targets[result->targetsSize].remainingPathIndex = elemDepth;
+ continue;
+ }
+
+ /* Can we store the node in the array of candidates for deep-search? */
+ if(*nextSize <= *nextCount) {
+ UA_NodeId *tempNext =
+ (UA_NodeId*)UA_realloc(*next, sizeof(UA_NodeId) * (*nextSize) * 2);
+ if(!tempNext) {
+ result->statusCode = UA_STATUSCODE_BADOUTOFMEMORY;
+ return;
+ }
+ *next = tempNext;
+ (*nextSize) *= 2;
+ }
+
+ /* Add the node to the next array for the following path element */
+ result->statusCode = UA_NodeId_copy(&targetId->nodeId,
+ &(*next)[*nextCount]);
+ if(result->statusCode != UA_STATUSCODE_GOOD)
+ return;
+ ++(*nextCount);
+ }
+}
+
+static void
+walkBrowsePathElement(UA_Server *server, UA_Session *session,
+ UA_BrowsePathResult *result, size_t *targetsSize,
+ const UA_RelativePathElement *elem, UA_UInt32 elemDepth,
+ const UA_QualifiedName *targetName,
+ const UA_NodeId *current, const size_t currentCount,
+ UA_NodeId **next, size_t *nextSize, size_t *nextCount) {
+ /* Return all references? */
+ 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_Boolean match = (rootRef->nodeClass == UA_NODECLASS_REFERENCETYPE);
+ UA_Nodestore_release(server, rootRef);
+ if(!match)
+ return;
+ }
+
+ /* Iterate over all nodes at the current depth-level */
+ for(size_t i = 0; i < currentCount; ++i) {
+ /* Get the node */
+ const UA_Node *node = UA_Nodestore_get(server, &current[i]);
+ if(!node) {
+ /* If we cannot find the node at depth 0, the starting node does not exist */
+ if(elemDepth == 0)
+ result->statusCode = UA_STATUSCODE_BADNODEIDUNKNOWN;
+ continue;
+ }
+
+ /* Test whether the current node has the target name required in the
+ * previous path element */
+ if(targetName && (targetName->namespaceIndex != node->browseName.namespaceIndex ||
+ !UA_String_equal(&targetName->name, &node->browseName.name))) {
+ UA_Nodestore_release(server, node);
+ continue;
+ }
+
+ /* Loop over the nodes references */
+ for(size_t r = 0; r < node->referencesSize &&
+ result->statusCode == UA_STATUSCODE_GOOD; ++r) {
+ UA_NodeReferenceKind *rk = &node->references[r];
+
+ /* Does the direction of the reference match? */
+ if(rk->isInverse != elem->isInverse)
+ continue;
+
+ /* Is the node relevant? */
+ if(!all_refs && !relevantReference(server, elem->includeSubtypes,
+ &elem->referenceTypeId, &rk->referenceTypeId))
+ continue;
+
+ /* Walk over the reference targets */
+ walkBrowsePathElementReferenceTargets(result, targetsSize, next, nextSize,
+ nextCount, elemDepth, rk);
+ }
+
+ UA_Nodestore_release(server, node);
+ }
+}
+
+/* This assumes that result->targets has enough room for all currentCount elements */
+static void
+addBrowsePathTargets(UA_Server *server, UA_Session *session,
+ UA_BrowsePathResult *result, const UA_QualifiedName *targetName,
+ UA_NodeId *current, size_t currentCount) {
+ for(size_t i = 0; i < currentCount; i++) {
+ const UA_Node *node = UA_Nodestore_get(server, &current[i]);
+ if(!node) {
+ UA_NodeId_deleteMembers(&current[i]);
+ continue;
+ }
+
+ /* Test whether the current node has the target name required in the
+ * previous path element */
+ UA_Boolean valid = targetName->namespaceIndex == node->browseName.namespaceIndex &&
+ UA_String_equal(&targetName->name, &node->browseName.name);
+
+ UA_Nodestore_release(server, node);
+
+ if(!valid) {
+ UA_NodeId_deleteMembers(&current[i]);
+ continue;
+ }
+
+ /* Move the nodeid to the target array */
+ UA_BrowsePathTarget_init(&result->targets[result->targetsSize]);
+ result->targets[result->targetsSize].targetId.nodeId = current[i];
+ result->targets[result->targetsSize].remainingPathIndex = UA_UINT32_MAX;
+ ++result->targetsSize;
+ }
+}
+
+static void
+walkBrowsePath(UA_Server *server, UA_Session *session, const UA_BrowsePath *path,
+ UA_BrowsePathResult *result, size_t targetsSize,
+ UA_NodeId **current, size_t *currentSize, size_t *currentCount,
+ UA_NodeId **next, size_t *nextSize, size_t *nextCount) {
+ UA_assert(*currentCount == 1);
+ UA_assert(*nextCount == 0);
+
+ /* Points to the targetName of the _previous_ path element */
+ const UA_QualifiedName *targetName = NULL;
+
+ /* Iterate over path elements */
+ UA_assert(path->relativePath.elementsSize > 0);
+ for(UA_UInt32 i = 0; i < path->relativePath.elementsSize; ++i) {
+ walkBrowsePathElement(server, session, result, &targetsSize,
+ &path->relativePath.elements[i], i, targetName,
+ *current, *currentCount, next, nextSize, nextCount);
+
+ /* Clean members of current */
+ for(size_t j = 0; j < *currentCount; j++)
+ UA_NodeId_deleteMembers(&(*current)[j]);
+ *currentCount = 0;
+
+ /* When no targets are left or an error occurred. None of next's
+ * elements will be copied to result->targets */
+ if(*nextCount == 0 || result->statusCode != UA_STATUSCODE_GOOD) {
+ UA_assert(*currentCount == 0);
+ UA_assert(*nextCount == 0);
+ return;
+ }
+
+ /* Exchange current and next for the next depth */
+ size_t tSize = *currentSize; size_t tCount = *currentCount; UA_NodeId *tT = *current;
+ *currentSize = *nextSize; *currentCount = *nextCount; *current = *next;
+ *nextSize = tSize; *nextCount = tCount; *next = tT;
+
+ /* Store the target name of the previous path element */
+ targetName = &path->relativePath.elements[i].targetName;
+ }
+
+ UA_assert(targetName != NULL);
+ UA_assert(*nextCount == 0);
+
+ /* After the last BrowsePathElement, move members from current to the
+ * result targets */
+
+ /* Realloc if more space is needed */
+ if(targetsSize < result->targetsSize + (*currentCount)) {
+ UA_BrowsePathTarget *newTargets =
+ (UA_BrowsePathTarget*)UA_realloc(result->targets, sizeof(UA_BrowsePathTarget) *
+ (result->targetsSize + (*currentCount)));
+ if(!newTargets) {
+ result->statusCode = UA_STATUSCODE_BADOUTOFMEMORY;
+ for(size_t i = 0; i < *currentCount; ++i)
+ UA_NodeId_deleteMembers(&(*current)[i]);
+ *currentCount = 0;
+ return;
+ }
+ result->targets = newTargets;
+ }
+
+ /* Move the elements of current to the targets */
+ addBrowsePathTargets(server, session, result, targetName, *current, *currentCount);
+ *currentCount = 0;
+}
+
+static void
+Operation_TranslateBrowsePathToNodeIds(UA_Server *server, UA_Session *session,
+ void *context, const UA_BrowsePath *path,
+ UA_BrowsePathResult *result) {
+ if(path->relativePath.elementsSize <= 0) {
+ result->statusCode = UA_STATUSCODE_BADNOTHINGTODO;
+ return;
+ }
+
+ /* RelativePath elements must not have an empty targetName */
+ for(size_t i = 0; i < path->relativePath.elementsSize; ++i) {
+ if(UA_QualifiedName_isNull(&path->relativePath.elements[i].targetName)) {
+ result->statusCode = UA_STATUSCODE_BADBROWSENAMEINVALID;
+ return;
+ }
+ }
+
+ /* Allocate memory for the targets */
+ size_t targetsSize = 10; /* When to realloc; the member count is stored in
+ * result->targetsSize */
+ result->targets =
+ (UA_BrowsePathTarget*)UA_malloc(sizeof(UA_BrowsePathTarget) * targetsSize);
+ if(!result->targets) {
+ result->statusCode = UA_STATUSCODE_BADOUTOFMEMORY;
+ return;
+ }
+
+ /* Allocate memory for two temporary arrays. One with the results for the
+ * previous depth of the path. The other for the new results at the current
+ * depth. The two arrays alternate as we descend down the tree. */
+ size_t currentSize = 10; /* When to realloc */
+ size_t currentCount = 0; /* Current elements */
+ UA_NodeId *current = (UA_NodeId*)UA_malloc(sizeof(UA_NodeId) * currentSize);
+ if(!current) {
+ result->statusCode = UA_STATUSCODE_BADOUTOFMEMORY;
+ UA_free(result->targets);
+ return;
+ }
+ size_t nextSize = 10; /* When to realloc */
+ size_t nextCount = 0; /* Current elements */
+ UA_NodeId *next = (UA_NodeId*)UA_malloc(sizeof(UA_NodeId) * nextSize);
+ if(!next) {
+ result->statusCode = UA_STATUSCODE_BADOUTOFMEMORY;
+ UA_free(result->targets);
+ UA_free(current);
+ return;
+ }
+
+ /* Copy the starting node into current */
+ result->statusCode = UA_NodeId_copy(&path->startingNode, &current[0]);
+ if(result->statusCode != UA_STATUSCODE_GOOD) {
+ UA_free(result->targets);
+ UA_free(current);
+ UA_free(next);
+ return;
+ }
+ currentCount = 1;
+
+ /* Walk the path elements */
+ walkBrowsePath(server, session, path, result, targetsSize,
+ &current, &currentSize, &currentCount,
+ &next, &nextSize, &nextCount);
+
+ UA_assert(currentCount == 0);
+ UA_assert(nextCount == 0);
+
+ /* No results => BadNoMatch status code */
+ if(result->targetsSize == 0 && result->statusCode == UA_STATUSCODE_GOOD)
+ result->statusCode = UA_STATUSCODE_BADNOMATCH;
+
+ /* Clean up the temporary arrays and the targets */
+ UA_free(current);
+ UA_free(next);
+ if(result->statusCode != UA_STATUSCODE_GOOD) {
+ for(size_t i = 0; i < result->targetsSize; ++i)
+ UA_BrowsePathTarget_deleteMembers(&result->targets[i]);
+ UA_free(result->targets);
+ result->targets = NULL;
+ result->targetsSize = 0;
+ }
+}
+
+UA_BrowsePathResult
+UA_Server_translateBrowsePathToNodeIds(UA_Server *server,
+ const UA_BrowsePath *browsePath) {
+ UA_BrowsePathResult result;
+ UA_BrowsePathResult_init(&result);
+ Operation_TranslateBrowsePathToNodeIds(server, &server->adminSession, NULL, browsePath, &result);
+ return result;
+}
+
+void
+Service_TranslateBrowsePathsToNodeIds(UA_Server *server, UA_Session *session,
+ const UA_TranslateBrowsePathsToNodeIdsRequest *request,
+ UA_TranslateBrowsePathsToNodeIdsResponse *response) {
+ UA_LOG_DEBUG_SESSION(server->config.logger, session,
+ "Processing TranslateBrowsePathsToNodeIdsRequest");
+
+ if(server->config.maxNodesPerTranslateBrowsePathsToNodeIds != 0 &&
+ request->browsePathsSize > server->config.maxNodesPerTranslateBrowsePathsToNodeIds) {
+ response->responseHeader.serviceResult = UA_STATUSCODE_BADTOOMANYOPERATIONS;
+ return;
+ }
+
+ response->responseHeader.serviceResult =
+ UA_Server_processServiceOperations(server, session,
+ (UA_ServiceOperation)Operation_TranslateBrowsePathToNodeIds,
+ NULL, &request->browsePathsSize, &UA_TYPES[UA_TYPES_BROWSEPATH],
+ &response->resultsSize, &UA_TYPES[UA_TYPES_BROWSEPATHRESULT]);
+}
+
+void Service_RegisterNodes(UA_Server *server, UA_Session *session,
+ const UA_RegisterNodesRequest *request,
+ UA_RegisterNodesResponse *response) {
+ UA_LOG_DEBUG_SESSION(server->config.logger, session,
+ "Processing RegisterNodesRequest");
+
+ //TODO: hang the nodeids to the session if really needed
+ if(request->nodesToRegisterSize == 0) {
+ response->responseHeader.serviceResult = UA_STATUSCODE_BADNOTHINGTODO;
+ return;
+ }
+
+ if(server->config.maxNodesPerRegisterNodes != 0 &&
+ request->nodesToRegisterSize > server->config.maxNodesPerRegisterNodes) {
+ response->responseHeader.serviceResult = UA_STATUSCODE_BADTOOMANYOPERATIONS;
+ return;
+ }
+
+ response->responseHeader.serviceResult =
+ UA_Array_copy(request->nodesToRegister, request->nodesToRegisterSize,
+ (void**)&response->registeredNodeIds, &UA_TYPES[UA_TYPES_NODEID]);
+ if(response->responseHeader.serviceResult == UA_STATUSCODE_GOOD)
+ response->registeredNodeIdsSize = request->nodesToRegisterSize;
+}
+
+void Service_UnregisterNodes(UA_Server *server, UA_Session *session,
+ const UA_UnregisterNodesRequest *request,
+ UA_UnregisterNodesResponse *response) {
+ UA_LOG_DEBUG_SESSION(server->config.logger, session,
+ "Processing UnRegisterNodesRequest");
+
+ //TODO: remove the nodeids from the session if really needed
+ if(request->nodesToUnregisterSize == 0)
+ response->responseHeader.serviceResult = UA_STATUSCODE_BADNOTHINGTODO;
+
+ if(server->config.maxNodesPerRegisterNodes != 0 &&
+ request->nodesToUnregisterSize > server->config.maxNodesPerRegisterNodes) {
+ response->responseHeader.serviceResult = UA_STATUSCODE_BADTOOMANYOPERATIONS;
+ return;
+ }
+}
+
+/*********************************** amalgamated original file "/home/jvoe/open62541/src/server/ua_services_call.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 (c) Chris Iatrou
+ * Copyright 2015-2017 (c) Florian Palm
+ * Copyright 2015-2017 (c) Julius Pfrommer, Fraunhofer IOSB
+ * Copyright 2015-2016 (c) Sten Grüner
+ * Copyright 2015 (c) Oleksiy Vasylyev
+ * Copyright 2016 (c) LEvertz
+ * Copyright 2017 (c) Stefan Profanter, fortiss GmbH
+ * Copyright 2017 (c) Julian Grothoff
+ */
+
+
+#ifdef UA_ENABLE_METHODCALLS /* conditional compilation */
+
+static const UA_VariableNode *
+getArgumentsVariableNode(UA_Server *server, const UA_MethodNode *ofMethod,
+ 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];
+
+ if(rk->isInverse != false)
+ continue;
+
+ if(!UA_NodeId_equal(&hasProperty, &rk->referenceTypeId))
+ continue;
+
+ for(size_t j = 0; j < rk->targetIdsSize; ++j) {
+ const UA_Node *refTarget =
+ server->config.nodestore.getNode(server->config.nodestore.context,
+ &rk->targetIds[j].nodeId);
+ 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;
+ }
+ server->config.nodestore.releaseNode(server->config.nodestore.context,
+ refTarget);
+ }
+ }
+ return NULL;
+}
+
+static UA_StatusCode
+typeCheckArguments(UA_Server *server, UA_Session *session,
+ const UA_VariableNode *argRequirements, size_t argsSize,
+ UA_Variant *args, UA_StatusCode *inputArgumentResults) {
+ /* Verify that we have a Variant containing UA_Argument (scalar or array) in
+ * the "InputArguments" node */
+ if(argRequirements->valueSource != UA_VALUESOURCE_DATA)
+ return UA_STATUSCODE_BADINTERNALERROR;
+ if(!argRequirements->value.data.value.hasValue)
+ return UA_STATUSCODE_BADINTERNALERROR;
+ if(argRequirements->value.data.value.value.type != &UA_TYPES[UA_TYPES_ARGUMENT])
+ return UA_STATUSCODE_BADINTERNALERROR;
+
+ /* Verify the number of arguments. A scalar argument value is interpreted as
+ * an array of length 1. */
+ size_t argReqsSize = argRequirements->value.data.value.value.arrayLength;
+ if(UA_Variant_isScalar(&argRequirements->value.data.value.value))
+ argReqsSize = 1;
+ if(argReqsSize > argsSize)
+ return UA_STATUSCODE_BADARGUMENTSMISSING;
+ if(argReqsSize < argsSize)
+ return UA_STATUSCODE_BADTOOMANYARGUMENTS;
+
+ /* Type-check every argument against the definition */
+ UA_Argument *argReqs = (UA_Argument*)argRequirements->value.data.value.value.data;
+ 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))
+ return UA_STATUSCODE_BADTYPEMISMATCH;
+ }
+ return UA_STATUSCODE_GOOD;
+}
+
+static UA_StatusCode
+validMethodArguments(UA_Server *server, UA_Session *session, const UA_MethodNode *method,
+ const UA_CallMethodRequest *request,
+ UA_StatusCode *inputArgumentResults) {
+ /* Get the input arguments node */
+ const UA_VariableNode *inputArguments =
+ getArgumentsVariableNode(server, method, UA_STRING("InputArguments"));
+ UA_StatusCode retval = UA_STATUSCODE_GOOD;
+ if(!inputArguments) {
+ if(request->inputArgumentsSize > 0)
+ retval = UA_STATUSCODE_BADINVALIDARGUMENT;
+ return retval;
+ }
+
+ /* Verify the request */
+ retval = typeCheckArguments(server, session, inputArguments,
+ request->inputArgumentsSize,
+ request->inputArguments,
+ inputArgumentResults);
+
+ /* Release the input arguments node */
+ server->config.nodestore.releaseNode(server->config.nodestore.context,
+ (const UA_Node*)inputArguments);
+ return retval;
+}
+
+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 void
+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) {
+ result->statusCode = UA_STATUSCODE_BADNODECLASSINVALID;
+ return;
+ }
+
+ /* Verify the method's NodeClass */
+ if(method->nodeClass != UA_NODECLASS_METHOD) {
+ result->statusCode = UA_STATUSCODE_BADNODECLASSINVALID;
+ return;
+ }
+
+ /* Is there a method to execute? */
+ if(!method->method) {
+ result->statusCode = UA_STATUSCODE_BADINTERNALERROR;
+ return;
+ }
+
+ /* 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_Boolean found = false;
+ for(size_t i = 0; i < object->referencesSize && !found; ++i) {
+ UA_NodeReferenceKind *rk = &object->references[i];
+ if(rk->isInverse)
+ continue;
+ if(!isNodeInTree(&server->config.nodestore, &rk->referenceTypeId,
+ &hasComponentNodeId, &hasSubTypeNodeId, 1))
+ continue;
+ for(size_t j = 0; j < rk->targetIdsSize; ++j) {
+ if(UA_NodeId_equal(&rk->targetIds[j].nodeId, &request->methodId)) {
+ found = true;
+ break;
+ }
+ }
+ }
+ if(!found) {
+ result->statusCode = UA_STATUSCODE_BADMETHODINVALID;
+ return;
+ }
+
+ /* Verify access rights */
+ UA_Boolean executable = method->executable;
+ if(session != &server->adminSession)
+ executable = executable &&
+ server->config.accessControl.getUserExecutableOnObject(server,
+ &server->config.accessControl, &session->sessionId,
+ session->sessionHandle, &request->methodId, method->context,
+ &request->objectId, object->context);
+ if(!executable) {
+ result->statusCode = UA_STATUSCODE_BADNOTWRITABLE; // There is no NOTEXECUTABLE?
+ return;
+ }
+
+ /* Verify Input Arguments */
+ result->statusCode = validMethodArguments(server, session, method, request, result->inputArgumentResults);
+
+ /* Return inputArgumentResults only for BADINVALIDARGUMENT */
+ if(result->statusCode != UA_STATUSCODE_BADINVALIDARGUMENT) {
+ UA_Array_delete(result->inputArgumentResults, result->inputArgumentResultsSize,
+ &UA_TYPES[UA_TYPES_STATUSCODE]);
+ result->inputArgumentResults = NULL;
+ result->inputArgumentResultsSize = 0;
+ }
+
+ /* Error during type-checking? */
+ if(result->statusCode != UA_STATUSCODE_GOOD)
+ return;
+
+ /* Get the output arguments node */
+ const UA_VariableNode *outputArguments =
+ getArgumentsVariableNode(server, method, UA_STRING("OutputArguments"));
+
+ /* Allocate the output arguments array */
+ if(outputArguments) {
+ if(outputArguments->value.data.value.value.arrayLength > 0) {
+ result->outputArguments = (UA_Variant*)
+ UA_Array_new(outputArguments->value.data.value.value.arrayLength,
+ &UA_TYPES[UA_TYPES_VARIANT]);
+ if(!result->outputArguments) {
+ result->statusCode = UA_STATUSCODE_BADOUTOFMEMORY;
+ return;
+ }
+ result->outputArgumentsSize = outputArguments->value.data.value.value.arrayLength;
+ }
+
+ /* Release the output arguments node */
+ server->config.nodestore.releaseNode(server->config.nodestore.context,
+ (const UA_Node*)outputArguments);
+ }
+
+ /* Call the method */
+ result->statusCode = method->method(server, &session->sessionId, session->sessionHandle,
+ &method->nodeId, method->context,
+ &object->nodeId, object->context,
+ request->inputArgumentsSize, request->inputArguments,
+ result->outputArgumentsSize, result->outputArguments);
+ /* TODO: Verify Output matches the argument definition */
+}
+
+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*)
+ server->config.nodestore.getNode(server->config.nodestore.context,
+ &request->methodId);
+ if(!method) {
+ result->statusCode = UA_STATUSCODE_BADMETHODINVALID;
+ return;
+ }
+
+ /* Get the object node */
+ const UA_ObjectNode *object = (const UA_ObjectNode*)
+ server->config.nodestore.getNode(server->config.nodestore.context,
+ &request->objectId);
+ if(!object) {
+ result->statusCode = UA_STATUSCODE_BADNODEIDINVALID;
+ server->config.nodestore.releaseNode(server->config.nodestore.context,
+ (const UA_Node*)method);
+ return;
+ }
+
+ /* Continue with method and object as context */
+ callWithMethodAndObject(server, session, request, result, method, object);
+
+ /* Release the method and object node */
+ server->config.nodestore.releaseNode(server->config.nodestore.context,
+ (const UA_Node*)method);
+ server->config.nodestore.releaseNode(server->config.nodestore.context,
+ (const UA_Node*)object);
+}
+
+void Service_Call(UA_Server *server, UA_Session *session,
+ const UA_CallRequest *request,
+ UA_CallResponse *response) {
+ UA_LOG_DEBUG_SESSION(server->config.logger, session,
+ "Processing CallRequest");
+
+ if(server->config.maxNodesPerMethodCall != 0 &&
+ request->methodsToCallSize > server->config.maxNodesPerMethodCall) {
+ response->responseHeader.serviceResult = UA_STATUSCODE_BADTOOMANYOPERATIONS;
+ return;
+ }
+
+ 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_CallMethodResult UA_EXPORT
+UA_Server_call(UA_Server *server, const UA_CallMethodRequest *request) {
+ UA_CallMethodResult result;
+ UA_CallMethodResult_init(&result);
+ Operation_CallMethod(server, &server->adminSession, NULL, request, &result);
+ return result;
+}
+
+#endif /* UA_ENABLE_METHODCALLS */
+
+/*********************************** amalgamated original file "/home/jvoe/open62541/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
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * Copyright 2014-2018 (c) Julius Pfrommer, Fraunhofer IOSB
+ * Copyright 2014-2017 (c) Florian Palm
+ * Copyright 2014-2016 (c) Sten Grüner
+ * Copyright 2015 (c) Chris Iatrou
+ * Copyright 2015 (c) Oleksiy Vasylyev
+ * Copyright 2017 (c) Stefan Profanter, fortiss GmbH
+ * Copyright 2017-2018 (c) Mark Giraud, Fraunhofer IOSB
+ */
+
+
+static UA_StatusCode
+signCreateSessionResponse(UA_Server *server, UA_SecureChannel *channel,
+ const UA_CreateSessionRequest *request,
+ UA_CreateSessionResponse *response) {
+ if(channel->securityMode != UA_MESSAGESECURITYMODE_SIGN &&
+ channel->securityMode != UA_MESSAGESECURITYMODE_SIGNANDENCRYPT)
+ return UA_STATUSCODE_GOOD;
+
+ const UA_SecurityPolicy *const securityPolicy = channel->securityPolicy;
+ UA_SignatureData *signatureData = &response->serverSignature;
+
+ /* Prepare the signature */
+ size_t signatureSize = securityPolicy->certificateSigningAlgorithm.
+ getLocalSignatureSize(securityPolicy, channel->channelContext);
+ UA_StatusCode retval = UA_String_copy(&securityPolicy->certificateSigningAlgorithm.uri,
+ &signatureData->algorithm);
+ retval |= UA_ByteString_allocBuffer(&signatureData->signature, signatureSize);
+ if(retval != UA_STATUSCODE_GOOD)
+ return retval;
+
+ /* Allocate a temp buffer */
+ size_t dataToSignSize = request->clientCertificate.length + request->clientNonce.length;
+ UA_ByteString dataToSign;
+ retval = UA_ByteString_allocBuffer(&dataToSign, dataToSignSize);
+ if(retval != UA_STATUSCODE_GOOD)
+ return retval; /* signatureData->signature is cleaned up with the response */
+
+ /* Sign the signature */
+ memcpy(dataToSign.data, request->clientCertificate.data, request->clientCertificate.length);
+ memcpy(dataToSign.data + request->clientCertificate.length,
+ request->clientNonce.data, request->clientNonce.length);
+ retval = securityPolicy->certificateSigningAlgorithm.
+ sign(securityPolicy, channel->channelContext, &dataToSign, &signatureData->signature);
+
+ /* Clean up */
+ UA_ByteString_deleteMembers(&dataToSign);
+ return retval;
+}
+
+void
+Service_CreateSession(UA_Server *server, UA_SecureChannel *channel,
+ const UA_CreateSessionRequest *request,
+ UA_CreateSessionResponse *response) {
+ if(!channel) {
+ response->responseHeader.serviceResult = UA_STATUSCODE_BADINTERNALERROR;
+ return;
+ }
+
+ if(!channel->connection) {
+ response->responseHeader.serviceResult = UA_STATUSCODE_BADINTERNALERROR;
+ return;
+ }
+
+ UA_LOG_DEBUG_CHANNEL(server->config.logger, channel, "Trying to create session");
+
+ if(channel->securityMode == UA_MESSAGESECURITYMODE_SIGN ||
+ channel->securityMode == UA_MESSAGESECURITYMODE_SIGNANDENCRYPT) {
+ /* Compare the clientCertificate with the remoteCertificate of the channel.
+ * Both the clientCertificate of this request and the remoteCertificate
+ * of the channel may contain a partial or a complete certificate chain.
+ * The compareCertificate function of the channelModule will compare the
+ * first certificate of each chain. The end certificate shall be located
+ * first in the chain according to the OPC UA specification Part 6 (1.04),
+ * chapter 6.2.3.*/
+ if(channel->securityPolicy->channelModule.compareCertificate(channel->channelContext,
+ &request->clientCertificate) != UA_STATUSCODE_GOOD) {
+ response->responseHeader.serviceResult = UA_STATUSCODE_BADCERTIFICATEINVALID;
+ return;
+ }
+ }
+
+ if(channel->securityToken.channelId == 0) {
+ response->responseHeader.serviceResult = UA_STATUSCODE_BADSECURECHANNELIDINVALID;
+ return;
+ }
+
+ if(!UA_ByteString_equal(&channel->securityPolicy->policyUri,
+ &UA_SECURITY_POLICY_NONE_URI) &&
+ request->clientNonce.length < 32) {
+ response->responseHeader.serviceResult = UA_STATUSCODE_BADNONCEINVALID;
+ return;
+ }
+
+ /* TODO: Compare application URI with certificate uri (decode certificate) */
+ UA_CertificateVerification *cv = channel->securityPolicy->certificateVerification;
+ if(cv && cv->verifyApplicationURI) {
+ response->responseHeader.serviceResult =
+ cv->verifyApplicationURI(cv->context, &request->clientCertificate,
+ &request->clientDescription.applicationUri);
+ if(response->responseHeader.serviceResult != UA_STATUSCODE_GOOD)
+ return;
+ }
+
+ UA_Session *newSession = NULL;
+ response->responseHeader.serviceResult =
+ UA_SessionManager_createSession(&server->sessionManager, channel, request, &newSession);
+ if(response->responseHeader.serviceResult != UA_STATUSCODE_GOOD) {
+ UA_LOG_DEBUG_CHANNEL(server->config.logger, channel,
+ "Processing CreateSessionRequest failed");
+ return;
+ }
+
+ UA_assert(newSession != NULL);
+
+ /* Allocate the response */
+ response->serverEndpoints = (UA_EndpointDescription *)
+ UA_Array_new(server->config.endpointsSize,
+ &UA_TYPES[UA_TYPES_ENDPOINTDESCRIPTION]);
+ if(!response->serverEndpoints) {
+ response->responseHeader.serviceResult = UA_STATUSCODE_BADOUTOFMEMORY;
+ UA_SessionManager_removeSession(&server->sessionManager,
+ &newSession->header.authenticationToken);
+ return;
+ }
+ response->serverEndpointsSize = server->config.endpointsSize;
+
+ /* Copy the server's endpointdescriptions into the response */
+ for(size_t i = 0; i < server->config.endpointsSize; ++i)
+ response->responseHeader.serviceResult |=
+ UA_EndpointDescription_copy(&server->config.endpoints[i].endpointDescription,
+ &response->serverEndpoints[i]);
+ if(response->responseHeader.serviceResult != UA_STATUSCODE_GOOD) {
+ UA_SessionManager_removeSession(&server->sessionManager,
+ &newSession->header.authenticationToken);
+ return;
+ }
+
+ /* Mirror back the endpointUrl */
+ for(size_t i = 0; i < response->serverEndpointsSize; ++i) {
+ UA_String_deleteMembers(&response->serverEndpoints[i].endpointUrl);
+ response->responseHeader.serviceResult |=
+ UA_String_copy(&request->endpointUrl,
+ &response->serverEndpoints[i].endpointUrl);
+ }
+
+ /* Attach the session to the channel. But don't activate for now. */
+ UA_Session_attachToSecureChannel(newSession, channel);
+
+ /* Fill the session information */
+ newSession->maxResponseMessageSize = request->maxResponseMessageSize;
+ newSession->maxRequestMessageSize =
+ channel->connection->localConf.maxMessageSize;
+ response->responseHeader.serviceResult |=
+ UA_ApplicationDescription_copy(&request->clientDescription,
+ &newSession->clientDescription);
+
+ /* Prepare the response */
+ response->sessionId = newSession->sessionId;
+ response->revisedSessionTimeout = (UA_Double)newSession->timeout;
+ response->authenticationToken = newSession->header.authenticationToken;
+ response->responseHeader.serviceResult |=
+ UA_String_copy(&request->sessionName, &newSession->sessionName);
+
+ UA_ByteString_init(&response->serverCertificate);
+
+ if(server->config.endpointsSize > 0)
+ for(size_t i = 0; i < response->serverEndpointsSize; ++i) {
+ if(response->serverEndpoints[i].securityMode==channel->securityMode &&
+ UA_ByteString_equal(&response->serverEndpoints[i].securityPolicyUri,
+ &channel->securityPolicy->policyUri) &&
+ UA_String_equal(&response->serverEndpoints[i].endpointUrl,
+ &request->endpointUrl))
+ {
+ response->responseHeader.serviceResult |=
+ UA_ByteString_copy(&response->serverEndpoints[i].serverCertificate,
+ &response->serverCertificate);
+ }
+ }
+
+ /* Create a session nonce */
+ response->responseHeader.serviceResult |= UA_Session_generateNonce(newSession);
+ response->responseHeader.serviceResult |=
+ UA_ByteString_copy(&newSession->serverNonce, &response->serverNonce);
+
+ /* Sign the signature */
+ response->responseHeader.serviceResult |=
+ signCreateSessionResponse(server, channel, request, response);
+
+ /* Failure -> remove the session */
+ if(response->responseHeader.serviceResult != UA_STATUSCODE_GOOD) {
+ UA_SessionManager_removeSession(&server->sessionManager,
+ &newSession->header.authenticationToken);
+ return;
+ }
+
+ UA_LOG_DEBUG_CHANNEL(server->config.logger, channel,
+ "Session " UA_PRINTF_GUID_FORMAT " created",
+ UA_PRINTF_GUID_DATA(newSession->sessionId.identifier.guid));
+}
+
+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;
+
+ if(!channel->securityPolicy)
+ return UA_STATUSCODE_BADINTERNALERROR;
+ const UA_SecurityPolicy *securityPolicy = channel->securityPolicy;
+ const UA_ByteString *localCertificate = &securityPolicy->localCertificate;
+
+ size_t dataToVerifySize = localCertificate->length + session->serverNonce.length;
+
+ UA_ByteString dataToVerify;
+ 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);
+
+ retval = securityPolicy->certificateSigningAlgorithm.verify(securityPolicy, channel->channelContext, &dataToVerify,
+ &request->clientSignature.signature);
+ UA_ByteString_deleteMembers(&dataToVerify);
+ return retval;
+}
+
+/* TODO: Check all of the following:
+ *
+ * Part 4, §5.6.3: When the ActivateSession Service is called for the first time
+ * then the Server shall reject the request if the SecureChannel is not same as
+ * the one associated with the CreateSession request. Subsequent calls to
+ * ActivateSession may be associated with different SecureChannels. If this is
+ * the case then 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 Server shall verify that the
+ * Client supplied a UserIdentityToken that is identical to the token currently
+ * associated with the Session. Once the Server accepts the new SecureChannel it
+ * shall reject requests sent via the old SecureChannel. */
+
+void
+Service_ActivateSession(UA_Server *server, UA_SecureChannel *channel,
+ UA_Session *session, const UA_ActivateSessionRequest *request,
+ UA_ActivateSessionResponse *response) {
+ UA_LOG_DEBUG_SESSION(server->config.logger, session, "Execute ActivateSession");
+
+ if(session->validTill < UA_DateTime_nowMonotonic()) {
+ UA_LOG_INFO_SESSION(server->config.logger, session,
+ "ActivateSession: SecureChannel %i wants "
+ "to activate, but the session has timed out",
+ channel->securityToken.channelId);
+ response->responseHeader.serviceResult =
+ UA_STATUSCODE_BADSESSIONIDINVALID;
+ return;
+ }
+
+ /* 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_INFO_SESSION(server->config.logger, session,
+ "Signature check failed with status code %s",
+ UA_StatusCode_name(response->responseHeader.serviceResult));
+ return;
+ }
+
+ /* Callback into userland access control */
+ response->responseHeader.serviceResult =
+ server->config.accessControl.activateSession(server, &server->config.accessControl,
+ &session->sessionId, &request->userIdentityToken,
+ &session->sessionHandle);
+ if(response->responseHeader.serviceResult != UA_STATUSCODE_GOOD) {
+ UA_LOG_INFO_SESSION(server->config.logger, session,
+ "ActivateSession: Could not generate a server nonce");
+ return;
+ }
+
+ if(session->header.channel && session->header.channel != channel) {
+ UA_LOG_INFO_SESSION(server->config.logger, session,
+ "ActivateSession: Detach from old channel");
+ /* Detach the old SecureChannel and attach the new */
+ UA_Session_detachFromSecureChannel(session);
+ UA_Session_attachToSecureChannel(session, channel);
+ }
+
+ /* Activate the session */
+ session->activated = true;
+ UA_Session_updateLifetime(session);
+
+ /* Generate a new session nonce for the next time ActivateSession is called */
+ response->responseHeader.serviceResult = UA_Session_generateNonce(session);
+ response->responseHeader.serviceResult |=
+ UA_ByteString_copy(&session->serverNonce, &response->serverNonce);
+ if(response->responseHeader.serviceResult != UA_STATUSCODE_GOOD) {
+ UA_Session_detachFromSecureChannel(session);
+ session->activated = false;
+ UA_LOG_INFO_SESSION(server->config.logger, session,
+ "ActivateSession: Could not generate a server nonce");
+ return;
+ }
+
+ UA_LOG_INFO_SESSION(server->config.logger, session,
+ "ActivateSession: Session activated");
+}
+
+void
+Service_CloseSession(UA_Server *server, UA_Session *session,
+ const UA_CloseSessionRequest *request,
+ UA_CloseSessionResponse *response) {
+ UA_LOG_INFO_SESSION(server->config.logger, session, "CloseSession");
+
+ /* Callback into userland access control */
+ server->config.accessControl.closeSession(server, &server->config.accessControl,
+ &session->sessionId, session->sessionHandle);
+ response->responseHeader.serviceResult =
+ UA_SessionManager_removeSession(&server->sessionManager,
+ &session->header.authenticationToken);
+}
+
+/*********************************** amalgamated original file "/home/jvoe/open62541/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
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * Copyright 2014-2018 (c) Julius Pfrommer, Fraunhofer IOSB
+ * Copyright 2015-2016 (c) Sten Grüner
+ * Copyright 2014-2017 (c) Florian Palm
+ * Copyright 2015 (c) Christian Fimmers
+ * Copyright 2015-2016 (c) Chris Iatrou
+ * Copyright 2015-2016 (c) Oleksiy Vasylyev
+ * Copyright 2015 (c) wuyangtang
+ * Copyright 2017 (c) Stefan Profanter, fortiss GmbH
+ * Copyright 2016 (c) Lorenz Haas
+ * Copyright 2017 (c) frax2222
+ * Copyright 2017 (c) Thomas Bender
+ * Copyright 2017 (c) Julian Grothoff
+ * Copyright 2017 (c) Jonas Green
+ * Copyright 2017 (c) Henrik Norrman
+ */
+
+
+/******************/
+/* Access Control */
+/******************/
+
+static UA_UInt32
+getUserWriteMask(UA_Server *server, const UA_Session *session,
+ const UA_Node *node) {
+ if(session == &server->adminSession)
+ return 0xFFFFFFFF; /* the local admin user has all rights */
+ return node->writeMask &
+ server->config.accessControl.getUserRightsMask(server, &server->config.accessControl,
+ &session->sessionId, session->sessionHandle,
+ &node->nodeId, node->context);
+}
+
+static UA_Byte
+getAccessLevel(UA_Server *server, const UA_Session *session,
+ const UA_VariableNode *node) {
+ if(session == &server->adminSession)
+ return 0xFF; /* the local admin user has all rights */
+ return node->accessLevel;
+}
+
+static UA_Byte
+getUserAccessLevel(UA_Server *server, const UA_Session *session,
+ const UA_VariableNode *node) {
+ if(session == &server->adminSession)
+ return 0xFF; /* the local admin user has all rights */
+ return node->accessLevel &
+ server->config.accessControl.getUserAccessLevel(server, &server->config.accessControl,
+ &session->sessionId, session->sessionHandle,
+ &node->nodeId, node->context);
+}
+
+static UA_Boolean
+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 */
+ return node->executable &
+ server->config.accessControl.getUserExecutable(server, &server->config.accessControl,
+ &session->sessionId, session->sessionHandle,
+ &node->nodeId, node->context);
+}
+
+/****************/
+/* Read Service */
+/****************/
+
+static UA_StatusCode
+readArrayDimensionsAttribute(const UA_VariableNode *vn, UA_DataValue *v) {
+ UA_Variant_setArray(&v->value, vn->arrayDimensions,
+ vn->arrayDimensionsSize, &UA_TYPES[UA_TYPES_UINT32]);
+ v->value.storageType = UA_VARIANT_DATA_NODELETE;
+ return UA_STATUSCODE_GOOD;
+}
+
+static void
+setScalarNoDelete(UA_Variant *v, const void * UA_RESTRICT p,
+ const UA_DataType *type) {
+ UA_Variant_setScalar(v, (void*)(uintptr_t)p, type);
+ v->storageType = UA_VARIANT_DATA_NODELETE;
+}
+
+static UA_StatusCode
+readIsAbstractAttribute(const UA_Node *node, UA_Variant *v) {
+ const UA_Boolean *isAbstract;
+ switch(node->nodeClass) {
+ case UA_NODECLASS_REFERENCETYPE:
+ isAbstract = &((const UA_ReferenceTypeNode*)node)->isAbstract;
+ break;
+ case UA_NODECLASS_OBJECTTYPE:
+ isAbstract = &((const UA_ObjectTypeNode*)node)->isAbstract;
+ break;
+ case UA_NODECLASS_VARIABLETYPE:
+ isAbstract = &((const UA_VariableTypeNode*)node)->isAbstract;
+ break;
+ case UA_NODECLASS_DATATYPE:
+ isAbstract = &((const UA_DataTypeNode*)node)->isAbstract;
+ break;
+ default:
+ return UA_STATUSCODE_BADATTRIBUTEIDINVALID;
+ }
+
+ setScalarNoDelete(v, isAbstract, &UA_TYPES[UA_TYPES_BOOLEAN]);
+ v->storageType = UA_VARIANT_DATA_NODELETE;
+ return UA_STATUSCODE_GOOD;
+}
+
+static UA_StatusCode
+readValueAttributeFromNode(UA_Server *server, UA_Session *session,
+ const UA_VariableNode *vn, UA_DataValue *v,
+ UA_NumericRange *rangeptr) {
+ if(vn->value.data.callback.onRead) {
+ vn->value.data.callback.onRead(server, &session->sessionId,
+ session->sessionHandle, &vn->nodeId,
+ vn->context, rangeptr, &vn->value.data.value);
+ const UA_Node *old = (const UA_Node *)vn;
+ /* Reopen the node to see the changes from onRead */
+ vn = (const UA_VariableNode*)UA_Nodestore_get(server, &vn->nodeId);
+ UA_Nodestore_release(server, old);
+ }
+ if(rangeptr)
+ return UA_Variant_copyRange(&vn->value.data.value.value, &v->value, *rangeptr);
+ *v = vn->value.data.value;
+ v->value.storageType = UA_VARIANT_DATA_NODELETE;
+ return UA_STATUSCODE_GOOD;
+}
+
+static UA_StatusCode
+readValueAttributeFromDataSource(UA_Server *server, UA_Session *session,
+ const UA_VariableNode *vn, UA_DataValue *v,
+ UA_TimestampsToReturn timestamps,
+ UA_NumericRange *rangeptr) {
+ if(!vn->value.dataSource.read)
+ return UA_STATUSCODE_BADINTERNALERROR;
+ UA_Boolean sourceTimeStamp = (timestamps == UA_TIMESTAMPSTORETURN_SOURCE ||
+ timestamps == UA_TIMESTAMPSTORETURN_BOTH);
+ return vn->value.dataSource.read(server, &session->sessionId, session->sessionHandle,
+ &vn->nodeId, vn->context, sourceTimeStamp, rangeptr, v);
+}
+
+static UA_StatusCode
+readValueAttributeComplete(UA_Server *server, UA_Session *session,
+ const UA_VariableNode *vn, UA_TimestampsToReturn timestamps,
+ const UA_String *indexRange, UA_DataValue *v) {
+ /* Compute the index range */
+ UA_NumericRange range;
+ UA_NumericRange *rangeptr = NULL;
+ UA_StatusCode retval = UA_STATUSCODE_GOOD;
+ if(indexRange && indexRange->length > 0) {
+ retval = UA_NumericRange_parseFromString(&range, indexRange);
+ if(retval != UA_STATUSCODE_GOOD)
+ return retval;
+ 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);
+
+ /* Clean up */
+ if(rangeptr)
+ UA_free(range.dimensions);
+ return retval;
+}
+
+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);
+}
+
+static const UA_String binEncoding = {sizeof("Default Binary")-1, (UA_Byte*)"Default Binary"};
+static const UA_String xmlEncoding = {sizeof("Default XML")-1, (UA_Byte*)"Default XML"};
+static const UA_String jsonEncoding = {sizeof("Default JSON")-1, (UA_Byte*)"Default JSON"};
+
+#define CHECK_NODECLASS(CLASS) \
+ if(!(node->nodeClass & (CLASS))) { \
+ retval = UA_STATUSCODE_BADATTRIBUTEIDINVALID; \
+ break; \
+ }
+
+/* Returns a datavalue that may point into the node via the
+ * UA_VARIANT_DATA_NODELETE tag. Don't access the returned DataValue once the
+ * node has been released! */
+static void
+Read(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 %i", id->attributeId);
+
+ /* Only Binary Encoding is supported */
+ if(id->dataEncoding.name.length > 0 &&
+ !UA_String_equal(&binEncoding, &id->dataEncoding.name)) {
+ if(UA_String_equal(&xmlEncoding, &id->dataEncoding.name) ||
+ UA_String_equal(&jsonEncoding, &id->dataEncoding.name))
+ v->status = UA_STATUSCODE_BADDATAENCODINGUNSUPPORTED;
+ else
+ v->status = UA_STATUSCODE_BADDATAENCODINGINVALID;
+ v->hasStatus = true;
+ return;
+ }
+
+ /* Index range for an attribute other than value */
+ if(id->indexRange.length > 0 && id->attributeId != UA_ATTRIBUTEID_VALUE) {
+ v->hasStatus = true;
+ v->status = UA_STATUSCODE_BADINDEXRANGENODATA;
+ return;
+ }
+
+ /* Read the attribute */
+ UA_StatusCode retval = UA_STATUSCODE_GOOD;
+ switch(id->attributeId) {
+ case UA_ATTRIBUTEID_NODEID:
+ setScalarNoDelete(&v->value, &node->nodeId, &UA_TYPES[UA_TYPES_NODEID]);
+ break;
+ case UA_ATTRIBUTEID_NODECLASS:
+ setScalarNoDelete(&v->value, &node->nodeClass, &UA_TYPES[UA_TYPES_NODECLASS]);
+ break;
+ case UA_ATTRIBUTEID_BROWSENAME:
+ setScalarNoDelete(&v->value, &node->browseName, &UA_TYPES[UA_TYPES_QUALIFIEDNAME]);
+ break;
+ case UA_ATTRIBUTEID_DISPLAYNAME:
+ setScalarNoDelete(&v->value, &node->displayName, &UA_TYPES[UA_TYPES_LOCALIZEDTEXT]);
+ break;
+ case UA_ATTRIBUTEID_DESCRIPTION:
+ setScalarNoDelete(&v->value, &node->description, &UA_TYPES[UA_TYPES_LOCALIZEDTEXT]);
+ break;
+ case UA_ATTRIBUTEID_WRITEMASK:
+ setScalarNoDelete(&v->value, &node->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]);
+ break; }
+ case UA_ATTRIBUTEID_ISABSTRACT:
+ retval = readIsAbstractAttribute(node, &v->value);
+ break;
+ case UA_ATTRIBUTEID_SYMMETRIC:
+ CHECK_NODECLASS(UA_NODECLASS_REFERENCETYPE);
+ setScalarNoDelete(&v->value, &((const UA_ReferenceTypeNode*)node)->symmetric,
+ &UA_TYPES[UA_TYPES_BOOLEAN]);
+ break;
+ case UA_ATTRIBUTEID_INVERSENAME:
+ CHECK_NODECLASS(UA_NODECLASS_REFERENCETYPE);
+ setScalarNoDelete(&v->value, &((const UA_ReferenceTypeNode*)node)->inverseName,
+ &UA_TYPES[UA_TYPES_LOCALIZEDTEXT]);
+ break;
+ case UA_ATTRIBUTEID_CONTAINSNOLOOPS:
+ CHECK_NODECLASS(UA_NODECLASS_VIEW);
+ setScalarNoDelete(&v->value, &((const UA_ViewNode*)node)->containsNoLoops,
+ &UA_TYPES[UA_TYPES_BOOLEAN]);
+ break;
+ case UA_ATTRIBUTEID_EVENTNOTIFIER:
+ CHECK_NODECLASS(UA_NODECLASS_VIEW | UA_NODECLASS_OBJECT);
+ setScalarNoDelete(&v->value, &((const UA_ViewNode*)node)->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) {
+ /* The access to a value variable is granted via the AccessLevel
+ * and UserAccessLevel attributes */
+ UA_Byte accessLevel = getAccessLevel(server, session, (const UA_VariableNode*)node);
+ if(!(accessLevel & (UA_ACCESSLEVELMASK_READ))) {
+ retval = UA_STATUSCODE_BADNOTREADABLE;
+ break;
+ }
+ accessLevel = getUserAccessLevel(server, session,
+ (const UA_VariableNode*)node);
+ if(!(accessLevel & (UA_ACCESSLEVELMASK_READ))) {
+ retval = UA_STATUSCODE_BADUSERACCESSDENIED;
+ break;
+ }
+ }
+ retval = readValueAttributeComplete(server, session, (const UA_VariableNode*)node,
+ timestampsToReturn, &id->indexRange, v);
+ break;
+ }
+ case UA_ATTRIBUTEID_DATATYPE:
+ CHECK_NODECLASS(UA_NODECLASS_VARIABLE | UA_NODECLASS_VARIABLETYPE);
+ setScalarNoDelete(&v->value, &((const UA_VariableTypeNode*)node)->dataType,
+ &UA_TYPES[UA_TYPES_NODEID]);
+ break;
+ case UA_ATTRIBUTEID_VALUERANK:
+ CHECK_NODECLASS(UA_NODECLASS_VARIABLE | UA_NODECLASS_VARIABLETYPE);
+ setScalarNoDelete(&v->value, &((const UA_VariableTypeNode*)node)->valueRank,
+ &UA_TYPES[UA_TYPES_INT32]);
+ break;
+ case UA_ATTRIBUTEID_ARRAYDIMENSIONS:
+ CHECK_NODECLASS(UA_NODECLASS_VARIABLE | UA_NODECLASS_VARIABLETYPE);
+ retval = readArrayDimensionsAttribute((const UA_VariableNode*)node, v);
+ break;
+ case UA_ATTRIBUTEID_ACCESSLEVEL:
+ CHECK_NODECLASS(UA_NODECLASS_VARIABLE);
+ setScalarNoDelete(&v->value, &((const UA_VariableNode*)node)->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]);
+ break; }
+ case UA_ATTRIBUTEID_MINIMUMSAMPLINGINTERVAL:
+ CHECK_NODECLASS(UA_NODECLASS_VARIABLE);
+ setScalarNoDelete(&v->value, &((const UA_VariableNode*)node)->minimumSamplingInterval,
+ &UA_TYPES[UA_TYPES_DOUBLE]);
+ break;
+ case UA_ATTRIBUTEID_HISTORIZING:
+ CHECK_NODECLASS(UA_NODECLASS_VARIABLE);
+ setScalarNoDelete(&v->value, &((const UA_VariableNode*)node)->historizing,
+ &UA_TYPES[UA_TYPES_BOOLEAN]);
+ break;
+ case UA_ATTRIBUTEID_EXECUTABLE:
+ CHECK_NODECLASS(UA_NODECLASS_METHOD);
+ setScalarNoDelete(&v->value, &((const UA_MethodNode*)node)->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]);
+ break; }
+ default:
+ retval = UA_STATUSCODE_BADATTRIBUTEIDINVALID;
+ }
+
+ /* Return error code when reading has failed */
+ if(retval != UA_STATUSCODE_GOOD) {
+ v->hasStatus = true;
+ v->status = retval;
+ return;
+ }
+
+ v->hasValue = true;
+
+ /* Create server timestamp */
+ if(timestampsToReturn == UA_TIMESTAMPSTORETURN_SERVER ||
+ timestampsToReturn == UA_TIMESTAMPSTORETURN_BOTH) {
+ if (!v->hasServerTimestamp) {
+ v->serverTimestamp = UA_DateTime_now();
+ v->hasServerTimestamp = true;
+ }
+ }
+
+ /* Handle source time stamp */
+ if(id->attributeId == UA_ATTRIBUTEID_VALUE) {
+ if(timestampsToReturn == UA_TIMESTAMPSTORETURN_SERVER ||
+ timestampsToReturn == UA_TIMESTAMPSTORETURN_NEITHER) {
+ v->hasSourceTimestamp = false;
+ v->hasSourcePicoseconds = false;
+ } else if(!v->hasSourceTimestamp) {
+ v->sourceTimestamp = UA_DateTime_now();
+ v->hasSourceTimestamp = true;
+ }
+ }
+}
+
+static UA_StatusCode
+Operation_Read(UA_Server *server, UA_Session *session, UA_MessageContext *mc,
+ UA_TimestampsToReturn timestampsToReturn, const UA_ReadValueId *id) {
+ UA_DataValue dv;
+ UA_DataValue_init(&dv);
+
+ /* Get the node */
+ const UA_Node *node = UA_Nodestore_get(server, &id->nodeId);
+
+ /* Perform the read operation */
+ if(node) {
+ Read(node, server, session, timestampsToReturn, id, &dv);
+ } else {
+ dv.hasStatus = true;
+ dv.status = UA_STATUSCODE_BADNODEIDUNKNOWN;
+ }
+
+ /* Encode (and send) the results */
+ UA_StatusCode retval = UA_MessageContext_encode(mc, &dv, &UA_TYPES[UA_TYPES_DATAVALUE]);
+
+ /* Free copied data and release the node */
+ UA_Variant_deleteMembers(&dv.value);
+ UA_Nodestore_release(server, node);
+ return retval;
+}
+
+UA_StatusCode Service_Read(UA_Server *server, UA_Session *session, UA_MessageContext *mc,
+ const UA_ReadRequest *request, UA_ResponseHeader *responseHeader) {
+ UA_LOG_DEBUG_SESSION(server->config.logger, session,
+ "Processing ReadRequest");
+
+ /* Check if the timestampstoreturn is valid */
+ if(request->timestampsToReturn > UA_TIMESTAMPSTORETURN_NEITHER)
+ responseHeader->serviceResult = UA_STATUSCODE_BADTIMESTAMPSTORETURNINVALID;
+
+ if(request->nodesToReadSize == 0)
+ responseHeader->serviceResult = UA_STATUSCODE_BADNOTHINGTODO;
+
+ /* Check if maxAge is valid */
+ if(request->maxAge < 0)
+ responseHeader->serviceResult = UA_STATUSCODE_BADMAXAGEINVALID;
+
+ /* Check if there are too many operations */
+ if(server->config.maxNodesPerRead != 0 &&
+ request->nodesToReadSize > server->config.maxNodesPerRead)
+ responseHeader->serviceResult = UA_STATUSCODE_BADTOOMANYOPERATIONS;
+
+ /* Encode the response header */
+ UA_StatusCode retval =
+ UA_MessageContext_encode(mc, responseHeader, &UA_TYPES[UA_TYPES_RESPONSEHEADER]);
+ if(retval != UA_STATUSCODE_GOOD)
+ return retval;
+
+ /* Process nothing if we return an error code for the entire service */
+ UA_Int32 arraySize = (UA_Int32)request->nodesToReadSize;
+ if(responseHeader->serviceResult != UA_STATUSCODE_GOOD)
+ arraySize = 0;
+
+ /* Process all ReadValueIds */
+ retval = UA_MessageContext_encode(mc, &arraySize, &UA_TYPES[UA_TYPES_INT32]);
+ if(retval != UA_STATUSCODE_GOOD)
+ return retval;
+
+ for(UA_Int32 i = 0; i < arraySize; i++) {
+ retval = Operation_Read(server, session, mc, request->timestampsToReturn,
+ &request->nodesToRead[i]);
+ if(retval != UA_STATUSCODE_GOOD)
+ return retval;
+ }
+
+ /* Don't return any DiagnosticInfo */
+ arraySize = -1;
+ return UA_MessageContext_encode(mc, &arraySize, &UA_TYPES[UA_TYPES_INT32]);
+}
+
+UA_DataValue
+UA_Server_readWithSession(UA_Server *server, UA_Session *session,
+ const UA_ReadValueId *item,
+ UA_TimestampsToReturn timestampsToReturn) {
+ UA_DataValue dv;
+ UA_DataValue_init(&dv);
+
+ /* Get the node */
+ const UA_Node *node = UA_Nodestore_get(server, &item->nodeId);
+ if(!node) {
+ dv.hasStatus = true;
+ dv.status = UA_STATUSCODE_BADNODEIDUNKNOWN;
+ return dv;
+ }
+
+ /* Perform the read operation */
+ Read(node, server, session, timestampsToReturn, item, &dv);
+
+ /* Do we have to copy the result before releasing the node? */
+ if(dv.hasValue && dv.value.storageType == UA_VARIANT_DATA_NODELETE) {
+ UA_DataValue dv2;
+ UA_StatusCode retval = UA_DataValue_copy(&dv, &dv2);
+ if(retval == UA_STATUSCODE_GOOD) {
+ dv = dv2;
+ } else {
+ UA_DataValue_init(&dv);
+ dv.hasStatus = true;
+ dv.status = retval;
+ }
+ }
+
+ /* Release the node and return */
+ UA_Nodestore_release(server, node);
+ return dv;
+}
+
+/* Exposes the Read service to local users */
+UA_DataValue
+UA_Server_read(UA_Server *server, const UA_ReadValueId *item,
+ UA_TimestampsToReturn timestamps) {
+ return UA_Server_readWithSession(server, &server->adminSession, item, timestamps);
+}
+
+/* Used in inline functions exposing the Read service with more syntactic sugar
+ * for individual attributes */
+UA_StatusCode
+__UA_Server_read(UA_Server *server, const UA_NodeId *nodeId,
+ const UA_AttributeId attributeId, void *v) {
+ /* Call the read service */
+ UA_ReadValueId item;
+ UA_ReadValueId_init(&item);
+ item.nodeId = *nodeId;
+ item.attributeId = attributeId;
+ UA_DataValue dv = UA_Server_read(server, &item, UA_TIMESTAMPSTORETURN_NEITHER);
+
+ /* Check the return value */
+ UA_StatusCode retval = UA_STATUSCODE_GOOD;
+ if(dv.hasStatus)
+ retval = dv.status;
+ else if(!dv.hasValue)
+ retval = UA_STATUSCODE_BADUNEXPECTEDERROR;
+ if(retval != UA_STATUSCODE_GOOD) {
+ UA_DataValue_deleteMembers(&dv);
+ return retval;
+ }
+
+ if(attributeId == UA_ATTRIBUTEID_VALUE ||
+ attributeId == UA_ATTRIBUTEID_ARRAYDIMENSIONS) {
+ /* Return the entire variant */
+ memcpy(v, &dv.value, sizeof(UA_Variant));
+ } else {
+ /* Return the variant content only */
+ memcpy(v, dv.value.data, dv.value.type->memSize);
+ UA_free(dv.value.data);
+ }
+ return retval;
+}
+
+/*****************/
+/* Type Checking */
+/*****************/
+
+enum type_equivalence {
+ TYPE_EQUIVALENCE_NONE,
+ TYPE_EQUIVALENCE_ENUM,
+ TYPE_EQUIVALENCE_OPAQUE
+};
+
+static enum type_equivalence
+typeEquivalence(const UA_DataType *t) {
+ if(t->membersSize != 1 || !t->members[0].namespaceZero)
+ return TYPE_EQUIVALENCE_NONE;
+ if(t->members[0].memberTypeIndex == UA_TYPES_INT32)
+ return TYPE_EQUIVALENCE_ENUM;
+ if(t->members[0].memberTypeIndex == UA_TYPES_BYTE && t->members[0].isArray)
+ return TYPE_EQUIVALENCE_OPAQUE;
+ return TYPE_EQUIVALENCE_NONE;
+}
+
+const UA_NodeId subtypeId = {0, UA_NODEIDTYPE_NUMERIC, {UA_NS0ID_HASSUBTYPE}};
+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) {
+ /* Do not allow empty datatypes */
+ if(UA_NodeId_isNull(dataType))
+ return false;
+
+ /* No constraint (TODO: use variant instead) */
+ if(UA_NodeId_isNull(constraintDataType))
+ 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))
+ return true;
+
+ /* Is the value-type a subtype of the required type? */
+ if(isNodeInTree(&server->config.nodestore, dataType, constraintDataType, &subtypeId, 1))
+ return true;
+
+ /* Enum allows Int32 (only) */
+ if(UA_NodeId_equal(dataType, &UA_TYPES[UA_TYPES_INT32].typeId) &&
+ isNodeInTree(&server->config.nodestore, constraintDataType, &enumNodeId, &subtypeId, 1))
+ 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->config.nodestore, constraintDataType,
+ dataType, &subtypeId, 1))
+ return true;
+ }
+
+ return false;
+}
+
+/* Test whether a ValueRank and the given arraydimensions are compatible.
+ *
+ * 5.6.2 Variable NodeClass: If the maximum is unknown the value shall be 0. The
+ * number of elements shall be equal to the value of the ValueRank Attribute.
+ * This Attribute shall be null if ValueRank <= 0. */
+UA_Boolean
+compatibleValueRankArrayDimensions(UA_Server *server, UA_Session *session,
+ UA_Int32 valueRank, size_t arrayDimensionsSize) {
+ /* ValueRank invalid */
+ if(valueRank < UA_VALUERANK_SCALAR_OR_ONE_DIMENSION) {
+ UA_LOG_INFO_SESSION(server->config.logger, session, "The ValueRank is invalid (< -3)");
+ 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 */
+ if(valueRank <= UA_VALUERANK_ONE_OR_MORE_DIMENSIONS) {
+ if(arrayDimensionsSize > 0) {
+ UA_LOG_INFO_SESSION(server->config.logger, session,
+ "No ArrayDimensions can be defined for a ValueRank <= 0");
+ return false;
+ }
+ return true;
+ }
+
+ /* 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");
+ return false;
+ }
+ return true;
+}
+
+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 */
+ 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 */
+ 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 */
+ 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 */
+ if(valueRank != constraintValueRank)
+ return false;
+ break;
+ }
+ return true;
+}
+
+/* Check if the ValueRank allows for the value dimension. This is more
+ * permissive than checking for the ArrayDimensions attribute. Because the value
+ * can have dimensions if the ValueRank < 0 */
+static UA_Boolean
+compatibleValueRankValue(UA_Int32 valueRank, const UA_Variant *value) {
+ /* Invalid ValueRank */
+ if(valueRank < UA_VALUERANK_SCALAR_OR_ONE_DIMENSION)
+ return false;
+
+ /* Empty arrays (-1) always match */
+ if(!value->data)
+ return true;
+
+ size_t arrayDims = value->arrayDimensionsSize;
+ if(!arrayDims && !UA_Variant_isScalar(value))
+ arrayDims = 1; /* array but no arraydimensions -> implicit array dimension 1 */
+
+ /* 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 */
+ return (arrayDims <= 1);
+ 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);
+ default:
+ break;
+ }
+
+ UA_assert(valueRank >= UA_VALUERANK_ONE_OR_MORE_DIMENSIONS);
+
+ /* case 0: the value is an array with one or more dimensions */
+ return (arrayDims == (UA_UInt32)valueRank);
+}
+
+UA_Boolean
+compatibleArrayDimensions(size_t constraintArrayDimensionsSize,
+ const UA_UInt32 *constraintArrayDimensions,
+ size_t testArrayDimensionsSize,
+ const UA_UInt32 *testArrayDimensions) {
+ /* No array dimensions defined -> everything is permitted if the value rank fits */
+ if(constraintArrayDimensionsSize == 0)
+ return true;
+
+ /* Dimension count must match */
+ if(testArrayDimensionsSize != constraintArrayDimensionsSize)
+ return false;
+
+ /* Dimension lengths must match; zero in the constraint is a wildcard */
+ for(size_t i = 0; i < constraintArrayDimensionsSize; ++i) {
+ if(constraintArrayDimensions[i] != testArrayDimensions[i] &&
+ constraintArrayDimensions[i] != 0)
+ return false;
+ }
+ return true;
+}
+
+UA_Boolean
+compatibleValueArrayDimensions(const UA_Variant *value, size_t targetArrayDimensionsSize,
+ const UA_UInt32 *targetArrayDimensions) {
+ size_t valueArrayDimensionsSize = value->arrayDimensionsSize;
+ UA_UInt32 *valueArrayDimensions = value->arrayDimensions;
+ UA_UInt32 tempArrayDimensions;
+ if(valueArrayDimensions == 0 && !UA_Variant_isScalar(value)) {
+ valueArrayDimensionsSize = 1;
+ tempArrayDimensions = (UA_UInt32)value->arrayLength;
+ valueArrayDimensions = &tempArrayDimensions;
+ }
+ return compatibleArrayDimensions(targetArrayDimensionsSize, targetArrayDimensions,
+ valueArrayDimensionsSize, valueArrayDimensions);
+}
+
+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) {
+ /* Empty value */
+ if(!value->type) {
+ /* Empty value is allowed for BaseDataType */
+ if(UA_NodeId_equal(targetDataTypeId, &UA_TYPES[UA_TYPES_VARIANT].typeId) ||
+ UA_NodeId_equal(targetDataTypeId, &UA_NODEID_NULL))
+ return true;
+
+ /* Workaround: Allow empty value if the target data type is abstract */
+ const UA_Node *datatype = UA_Nodestore_get(server, targetDataTypeId);
+ if(datatype && datatype->nodeClass == UA_NODECLASS_DATATYPE) {
+ UA_Boolean isAbstract = ((const UA_DataTypeNode*)datatype)->isAbstract;
+ UA_Nodestore_release(server, datatype);
+ if(isAbstract)
+ return true;
+ }
+
+ UA_LOG_INFO(server->config.logger, UA_LOGCATEGORY_SERVER,
+ "Only Variables with data type BaseDataType may contain "
+ "a null (empty) value");
+ return false;
+ }
+
+ /* Has the value a subtype of the required type? BaseDataType (Variant) can
+ * be anything... */
+ if(!compatibleDataType(server, &value->type->typeId, targetDataTypeId, true))
+ 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))
+ return false;
+
+ /* Check if the valuerank allows for the value dimension */
+ return compatibleValueRankValue(targetValueRank, value);
+}
+
+/*****************/
+/* Write Service */
+/*****************/
+
+static void
+adjustValue(UA_Server *server, UA_Variant *value,
+ const UA_NodeId *targetDataTypeId) {
+ const UA_DataType *targetDataType = UA_findDataType(targetDataTypeId);
+ if(!targetDataType)
+ return;
+
+ /* A string is written to a byte array. the valuerank and array dimensions
+ * are checked later */
+ if(targetDataType == &UA_TYPES[UA_TYPES_BYTE] &&
+ value->type == &UA_TYPES[UA_TYPES_BYTESTRING] &&
+ UA_Variant_isScalar(value)) {
+ UA_ByteString *str = (UA_ByteString*)value->data;
+ value->type = &UA_TYPES[UA_TYPES_BYTE];
+ value->arrayLength = str->length;
+ value->data = str->data;
+ return;
+ }
+
+ /* An enum was sent as an int32, or an opaque type as a bytestring. This
+ * is detected with the typeIndex indicating the "true" datatype. */
+ enum type_equivalence te1 = typeEquivalence(targetDataType);
+ enum type_equivalence te2 = typeEquivalence(value->type);
+ if(te1 != TYPE_EQUIVALENCE_NONE && te1 == te2) {
+ value->type = targetDataType;
+ return;
+ }
+
+ /* No more possible equivalencies */
+}
+
+static UA_StatusCode
+writeArrayDimensionsAttribute(UA_Server *server, UA_Session *session,
+ UA_VariableNode *node, const UA_VariableTypeNode *type,
+ size_t arrayDimensionsSize, UA_UInt32 *arrayDimensions) {
+ UA_assert(node != NULL);
+ UA_assert(type != NULL);
+
+ /* 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)) {
+ 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)) {
+ UA_LOG_DEBUG(server->config.logger, UA_LOGCATEGORY_SERVER,
+ "Cannot write the ArrayDimensions. The ValueRank does not match.");
+ return UA_STATUSCODE_BADTYPEMISMATCH;
+ }
+
+ /* Check if the array dimensions match with the wildcards in the
+ * variabletype (dimension length 0) */
+ if(type->arrayDimensions &&
+ !compatibleArrayDimensions(type->arrayDimensionsSize, type->arrayDimensions,
+ arrayDimensionsSize, arrayDimensions)) {
+ UA_LOG_DEBUG(server->config.logger, UA_LOGCATEGORY_SERVER,
+ "Array dimensions in the variable type do not match");
+ return UA_STATUSCODE_BADTYPEMISMATCH;
+ }
+
+ /* Check if the current value is compatible with the array dimensions */
+ UA_DataValue value;
+ UA_DataValue_init(&value);
+ UA_StatusCode retval = readValueAttribute(server, session, node, &value);
+ if(retval != UA_STATUSCODE_GOOD)
+ return retval;
+ if(value.hasValue) {
+ if(!compatibleValueArrayDimensions(&value.value, arrayDimensionsSize, arrayDimensions))
+ retval = UA_STATUSCODE_BADTYPEMISMATCH;
+ UA_DataValue_deleteMembers(&value);
+ if(retval != UA_STATUSCODE_GOOD) {
+ UA_LOG_DEBUG(server->config.logger, UA_LOGCATEGORY_SERVER,
+ "Array dimensions in the current value do not match");
+ return retval;
+ }
+ }
+
+ /* Ok, apply */
+ UA_UInt32 *oldArrayDimensions = node->arrayDimensions;
+ size_t oldArrayDimensionsSize = node->arrayDimensionsSize;
+ retval = UA_Array_copy(arrayDimensions, arrayDimensionsSize,
+ (void**)&node->arrayDimensions,
+ &UA_TYPES[UA_TYPES_UINT32]);
+ if(retval != UA_STATUSCODE_GOOD)
+ return retval;
+ UA_Array_delete(oldArrayDimensions, oldArrayDimensionsSize, &UA_TYPES[UA_TYPES_UINT32]);
+ node->arrayDimensionsSize = arrayDimensionsSize;
+ return UA_STATUSCODE_GOOD;
+}
+
+/* Stack layout: ... | node | type */
+static UA_StatusCode
+writeValueRankAttribute(UA_Server *server, UA_Session *session,
+ UA_VariableNode *node, const UA_VariableTypeNode *type,
+ UA_Int32 valueRank) {
+ UA_assert(node != NULL);
+ UA_assert(type != NULL);
+
+ UA_Int32 constraintValueRank = type->valueRank;
+
+ /* 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))
+ return UA_STATUSCODE_BADINTERNALERROR;
+
+ /* Check if the valuerank of the variabletype allows the change. */
+ if(!compatibleValueRanks(valueRank, constraintValueRank))
+ return UA_STATUSCODE_BADTYPEMISMATCH;
+
+ /* Check if the new valuerank is compatible with the array dimensions. Use
+ * the read service to handle data sources. */
+ size_t arrayDims = node->arrayDimensionsSize;
+ if(arrayDims == 0) {
+ /* the value could be an array with no arrayDimensions defined.
+ dimensions zero indicate a scalar for compatibleValueRankArrayDimensions. */
+ UA_DataValue value;
+ UA_DataValue_init(&value);
+ UA_StatusCode retval = readValueAttribute(server, session, node, &value);
+ if(retval != UA_STATUSCODE_GOOD)
+ return retval;
+ if(!value.hasValue || !value.value.type) {
+ /* no value -> apply */
+ node->valueRank = valueRank;
+ return UA_STATUSCODE_GOOD;
+ }
+ if(!UA_Variant_isScalar(&value.value))
+ arrayDims = 1;
+ UA_DataValue_deleteMembers(&value);
+ }
+ if(!compatibleValueRankArrayDimensions(server, session, valueRank, arrayDims))
+ return UA_STATUSCODE_BADTYPEMISMATCH;
+
+ /* All good, apply the change */
+ node->valueRank = valueRank;
+ return UA_STATUSCODE_GOOD;
+}
+
+static UA_StatusCode
+writeDataTypeAttribute(UA_Server *server, UA_Session *session,
+ UA_VariableNode *node, const UA_VariableTypeNode *type,
+ const UA_NodeId *dataType) {
+ UA_assert(node != NULL);
+ UA_assert(type != NULL);
+
+ /* 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))
+ return UA_STATUSCODE_BADINTERNALERROR;
+
+ /* Does the new type match the constraints of the variabletype? */
+ if(!compatibleDataType(server, dataType, &type->dataType, false))
+ return UA_STATUSCODE_BADTYPEMISMATCH;
+
+ /* Check if the current value would match the new type */
+ UA_DataValue value;
+ UA_DataValue_init(&value);
+ UA_StatusCode retval = readValueAttribute(server, session, node, &value);
+ if(retval != UA_STATUSCODE_GOOD)
+ return retval;
+ if(value.hasValue) {
+ if(!compatibleValue(server, session, dataType, node->valueRank,
+ node->arrayDimensionsSize, node->arrayDimensions,
+ &value.value, NULL))
+ retval = UA_STATUSCODE_BADTYPEMISMATCH;
+ UA_DataValue_deleteMembers(&value);
+ if(retval != UA_STATUSCODE_GOOD) {
+ UA_LOG_DEBUG(server->config.logger, UA_LOGCATEGORY_SERVER,
+ "The current value does not match the new data type");
+ return retval;
+ }
+ }
+
+ /* Replace the datatype nodeid */
+ UA_NodeId dtCopy = node->dataType;
+ retval = UA_NodeId_copy(dataType, &node->dataType);
+ if(retval != UA_STATUSCODE_GOOD) {
+ node->dataType = dtCopy;
+ return retval;
+ }
+ UA_NodeId_deleteMembers(&dtCopy);
+ return UA_STATUSCODE_GOOD;
+}
+
+static UA_StatusCode
+writeValueAttributeWithoutRange(UA_VariableNode *node, const UA_DataValue *value) {
+ UA_DataValue new_value;
+ UA_StatusCode retval = UA_DataValue_copy(value, &new_value);
+ if(retval != UA_STATUSCODE_GOOD)
+ return retval;
+ UA_DataValue_deleteMembers(&node->value.data.value);
+ node->value.data.value = new_value;
+ return UA_STATUSCODE_GOOD;
+}
+
+static UA_StatusCode
+writeValueAttributeWithRange(UA_VariableNode *node, const UA_DataValue *value,
+ const UA_NumericRange *rangeptr) {
+ /* Value on both sides? */
+ if(value->status != node->value.data.value.status ||
+ !value->hasValue || !node->value.data.value.hasValue)
+ return UA_STATUSCODE_BADINDEXRANGEINVALID;
+
+ /* Make scalar a one-entry array for range matching */
+ UA_Variant editableValue;
+ const UA_Variant *v = &value->value;
+ if(UA_Variant_isScalar(&value->value)) {
+ editableValue = value->value;
+ editableValue.arrayLength = 1;
+ v = &editableValue;
+ }
+
+ /* Check that the type is an exact match and not only "compatible" */
+ if(!node->value.data.value.value.type || !v->type ||
+ !UA_NodeId_equal(&node->value.data.value.value.type->typeId,
+ &v->type->typeId))
+ return UA_STATUSCODE_BADTYPEMISMATCH;
+
+ /* Write the value */
+ UA_StatusCode retval = UA_Variant_setRangeCopy(&node->value.data.value.value,
+ v->data, v->arrayLength, *rangeptr);
+ if(retval != UA_STATUSCODE_GOOD)
+ return retval;
+
+ /* Write the status and timestamps */
+ node->value.data.value.hasStatus = value->hasStatus;
+ node->value.data.value.status = value->status;
+ node->value.data.value.hasSourceTimestamp = value->hasSourceTimestamp;
+ node->value.data.value.sourceTimestamp = value->sourceTimestamp;
+ node->value.data.value.hasSourcePicoseconds = value->hasSourcePicoseconds;
+ node->value.data.value.sourcePicoseconds = value->sourcePicoseconds;
+ return UA_STATUSCODE_GOOD;
+}
+
+/* Stack layout: ... | node */
+static UA_StatusCode
+writeValueAttribute(UA_Server *server, UA_Session *session,
+ UA_VariableNode *node, const UA_DataValue *value,
+ const UA_String *indexRange) {
+ UA_assert(node != NULL);
+
+ /* Parse the range */
+ UA_NumericRange range;
+ UA_NumericRange *rangeptr = NULL;
+ UA_StatusCode retval = UA_STATUSCODE_GOOD;
+ if(indexRange && indexRange->length > 0) {
+ retval = UA_NumericRange_parseFromString(&range, indexRange);
+ if(retval != UA_STATUSCODE_GOOD)
+ return retval;
+ rangeptr = &range;
+ }
+
+ /* Created an editable version. The data is not touched. Only the variant
+ * "container". */
+ UA_DataValue adjustedValue = *value;
+
+ /* Type checking. May change the type of editableValue */
+ if(value->hasValue && value->value.type) {
+ adjustValue(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
+ * extension object we check if the current node value is also an
+ * extension object. */
+ UA_Boolean compatible;
+ if(value->value.type->typeId.identifierType == UA_NODEIDTYPE_NUMERIC &&
+ value->value.type->typeId.identifier.numeric == UA_NS0ID_STRUCTURE) {
+ const UA_NodeId nodeDataType = UA_NODEID_NUMERIC(0, UA_NS0ID_STRUCTURE);
+ compatible = compatibleValue(server, session, &nodeDataType, node->valueRank,
+ node->arrayDimensionsSize, node->arrayDimensions,
+ &adjustedValue.value, rangeptr);
+ } else {
+ compatible = compatibleValue(server, session, &node->dataType, node->valueRank,
+ node->arrayDimensionsSize, node->arrayDimensions,
+ &adjustedValue.value, rangeptr);
+ }
+
+
+ if(!compatible) {
+ if(rangeptr)
+ UA_free(range.dimensions);
+ return UA_STATUSCODE_BADTYPEMISMATCH;
+ }
+ }
+
+ /* 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;
+ }
+
+ /* Ok, do it */
+ if(node->valueSource == UA_VALUESOURCE_DATA) {
+ if(!rangeptr)
+ retval = writeValueAttributeWithoutRange(node, &adjustedValue);
+ else
+ retval = writeValueAttributeWithRange(node, &adjustedValue, rangeptr);
+
+ /* Callback after writing */
+ if(retval == UA_STATUSCODE_GOOD && node->value.data.callback.onWrite)
+ node->value.data.callback.onWrite(server, &session->sessionId,
+ session->sessionHandle, &node->nodeId,
+ node->context, rangeptr,
+ &adjustedValue);
+ } else {
+ if(node->value.dataSource.write) {
+ retval = node->value.dataSource.write(server, &session->sessionId,
+ session->sessionHandle, &node->nodeId,
+ node->context, rangeptr, &adjustedValue);
+ } else {
+ retval = UA_STATUSCODE_BADWRITENOTSUPPORTED;
+ }
+ }
+
+ /* Clean up */
+ if(rangeptr)
+ UA_free(range.dimensions);
+ return retval;
+}
+
+static UA_StatusCode
+writeIsAbstractAttribute(UA_Node *node, UA_Boolean value) {
+ switch(node->nodeClass) {
+ case UA_NODECLASS_OBJECTTYPE:
+ ((UA_ObjectTypeNode*)node)->isAbstract = value;
+ break;
+ case UA_NODECLASS_REFERENCETYPE:
+ ((UA_ReferenceTypeNode*)node)->isAbstract = value;
+ break;
+ case UA_NODECLASS_VARIABLETYPE:
+ ((UA_VariableTypeNode*)node)->isAbstract = value;
+ break;
+ case UA_NODECLASS_DATATYPE:
+ ((UA_DataTypeNode*)node)->isAbstract = value;
+ break;
+ default:
+ return UA_STATUSCODE_BADNODECLASSINVALID;
+ }
+ return UA_STATUSCODE_GOOD;
+}
+
+/*****************/
+/* Write Service */
+/*****************/
+
+#define CHECK_DATATYPE_SCALAR(EXP_DT) \
+ if(!wvalue->value.hasValue || \
+ &UA_TYPES[UA_TYPES_##EXP_DT] != wvalue->value.value.type || \
+ !UA_Variant_isScalar(&wvalue->value.value)) { \
+ retval = UA_STATUSCODE_BADTYPEMISMATCH; \
+ break; \
+ }
+
+#define CHECK_DATATYPE_ARRAY(EXP_DT) \
+ if(!wvalue->value.hasValue || \
+ &UA_TYPES[UA_TYPES_##EXP_DT] != wvalue->value.value.type || \
+ UA_Variant_isScalar(&wvalue->value.value)) { \
+ retval = UA_STATUSCODE_BADTYPEMISMATCH; \
+ break; \
+ }
+
+#define CHECK_NODECLASS_WRITE(CLASS) \
+ if((node->nodeClass & (CLASS)) == 0) { \
+ retval = UA_STATUSCODE_BADNODECLASSINVALID; \
+ break; \
+ }
+
+#define CHECK_USERWRITEMASK(mask) \
+ if(!(userWriteMask & (mask))) { \
+ retval = UA_STATUSCODE_BADUSERACCESSDENIED; \
+ break; \
+ }
+
+#define GET_NODETYPE \
+ type = (const UA_VariableTypeNode*) \
+ getNodeType(server, node); \
+ if(!type) { \
+ retval = UA_STATUSCODE_BADTYPEMISMATCH; \
+ break; \
+ }
+
+/* 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) {
+ const void *value = wvalue->value.value.data;
+ UA_UInt32 userWriteMask = getUserWriteMask(server, session, node);
+ UA_StatusCode retval = UA_STATUSCODE_GOOD;
+
+ const UA_VariableTypeNode *type;
+
+ switch(wvalue->attributeId) {
+ case UA_ATTRIBUTEID_NODEID:
+ case UA_ATTRIBUTEID_NODECLASS:
+ case UA_ATTRIBUTEID_USERWRITEMASK:
+ case UA_ATTRIBUTEID_USERACCESSLEVEL:
+ case UA_ATTRIBUTEID_USEREXECUTABLE:
+ retval = UA_STATUSCODE_BADWRITENOTSUPPORTED;
+ break;
+ case UA_ATTRIBUTEID_BROWSENAME:
+ CHECK_USERWRITEMASK(UA_WRITEMASK_BROWSENAME);
+ CHECK_DATATYPE_SCALAR(QUALIFIEDNAME);
+ UA_QualifiedName_deleteMembers(&node->browseName);
+ UA_QualifiedName_copy((const UA_QualifiedName *)value, &node->browseName);
+ break;
+ case UA_ATTRIBUTEID_DISPLAYNAME:
+ CHECK_USERWRITEMASK(UA_WRITEMASK_DISPLAYNAME);
+ CHECK_DATATYPE_SCALAR(LOCALIZEDTEXT);
+ UA_LocalizedText_deleteMembers(&node->displayName);
+ UA_LocalizedText_copy((const UA_LocalizedText *)value, &node->displayName);
+ break;
+ case UA_ATTRIBUTEID_DESCRIPTION:
+ CHECK_USERWRITEMASK(UA_WRITEMASK_DESCRIPTION);
+ CHECK_DATATYPE_SCALAR(LOCALIZEDTEXT);
+ UA_LocalizedText_deleteMembers(&node->description);
+ UA_LocalizedText_copy((const UA_LocalizedText *)value, &node->description);
+ break;
+ case UA_ATTRIBUTEID_WRITEMASK:
+ CHECK_USERWRITEMASK(UA_WRITEMASK_WRITEMASK);
+ CHECK_DATATYPE_SCALAR(UINT32);
+ node->writeMask = *(const UA_UInt32*)value;
+ break;
+ case UA_ATTRIBUTEID_ISABSTRACT:
+ CHECK_USERWRITEMASK(UA_WRITEMASK_ISABSTRACT);
+ CHECK_DATATYPE_SCALAR(BOOLEAN);
+ retval = writeIsAbstractAttribute(node, *(const UA_Boolean*)value);
+ break;
+ case UA_ATTRIBUTEID_SYMMETRIC:
+ CHECK_NODECLASS_WRITE(UA_NODECLASS_REFERENCETYPE);
+ CHECK_USERWRITEMASK(UA_WRITEMASK_SYMMETRIC);
+ CHECK_DATATYPE_SCALAR(BOOLEAN);
+ ((UA_ReferenceTypeNode*)node)->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);
+ UA_LocalizedText_deleteMembers(&((UA_ReferenceTypeNode*)node)->inverseName);
+ UA_LocalizedText_copy((const UA_LocalizedText *)value,
+ &((UA_ReferenceTypeNode*)node)->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;
+ break;
+ case UA_ATTRIBUTEID_EVENTNOTIFIER:
+ CHECK_NODECLASS_WRITE(UA_NODECLASS_VIEW | UA_NODECLASS_OBJECT);
+ CHECK_USERWRITEMASK(UA_WRITEMASK_EVENTNOTIFIER);
+ CHECK_DATATYPE_SCALAR(BYTE);
+ ((UA_ViewNode*)node)->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) {
+ /* The access to a value variable is granted via the AccessLevel
+ * and UserAccessLevel attributes */
+ UA_Byte accessLevel = getAccessLevel(server, session, (const UA_VariableNode*)node);
+ if(!(accessLevel & (UA_ACCESSLEVELMASK_WRITE))) {
+ retval = UA_STATUSCODE_BADNOTWRITABLE;
+ break;
+ }
+ accessLevel = getUserAccessLevel(server, session,
+ (const UA_VariableNode*)node);
+ if(!(accessLevel & (UA_ACCESSLEVELMASK_WRITE))) {
+ retval = UA_STATUSCODE_BADUSERACCESSDENIED;
+ break;
+ }
+ } else { /* UA_NODECLASS_VARIABLETYPE */
+ CHECK_USERWRITEMASK(UA_WRITEMASK_VALUEFORVARIABLETYPE);
+ }
+ retval = writeValueAttribute(server, session, (UA_VariableNode*)node,
+ &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,
+ type, (const UA_NodeId*)value);
+ UA_Nodestore_release(server, (const UA_Node*)type);
+ break;
+ case UA_ATTRIBUTEID_VALUERANK:
+ 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,
+ type, *(const UA_Int32*)value);
+ UA_Nodestore_release(server, (const UA_Node*)type);
+ break;
+ case UA_ATTRIBUTEID_ARRAYDIMENSIONS:
+ 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,
+ type, wvalue->value.value.arrayLength,
+ (UA_UInt32 *)wvalue->value.value.data);
+ UA_Nodestore_release(server, (const UA_Node*)type);
+ break;
+ case UA_ATTRIBUTEID_ACCESSLEVEL:
+ CHECK_NODECLASS_WRITE(UA_NODECLASS_VARIABLE);
+ CHECK_USERWRITEMASK(UA_WRITEMASK_ACCESSLEVEL);
+ CHECK_DATATYPE_SCALAR(BYTE);
+ ((UA_VariableNode*)node)->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;
+ 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;
+ 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;
+ break;
+ default:
+ retval = UA_STATUSCODE_BADATTRIBUTEIDINVALID;
+ break;
+ }
+ if(retval != UA_STATUSCODE_GOOD)
+ UA_LOG_INFO_SESSION(server->config.logger, session,
+ "WriteRequest returned status code %s",
+ UA_StatusCode_name(retval));
+ return retval;
+}
+
+static void
+Operation_Write(UA_Server *server, UA_Session *session, void *context,
+ UA_WriteValue *wv, UA_StatusCode *result) {
+ *result = UA_Server_editNode(server, session, &wv->nodeId,
+ (UA_EditNodeCallback)copyAttributeIntoNode, wv);
+}
+
+void
+Service_Write(UA_Server *server, UA_Session *session,
+ const UA_WriteRequest *request,
+ UA_WriteResponse *response) {
+ UA_LOG_DEBUG_SESSION(server->config.logger, session,
+ "Processing WriteRequest");
+
+ if(server->config.maxNodesPerWrite != 0 &&
+ request->nodesToWriteSize > server->config.maxNodesPerWrite) {
+ response->responseHeader.serviceResult = UA_STATUSCODE_BADTOOMANYOPERATIONS;
+ return;
+ }
+
+ 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_StatusCode
+UA_Server_write(UA_Server *server, const UA_WriteValue *value) {
+ UA_StatusCode retval =
+ 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);
+ return retval;
+}
+
+/* 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_WriteValue wvalue;
+ UA_WriteValue_init(&wvalue);
+ wvalue.nodeId = *nodeId;
+ wvalue.attributeId = attributeId;
+ wvalue.value.hasValue = true;
+ if(attr_type != &UA_TYPES[UA_TYPES_VARIANT]) {
+ /* hacked cast. the target WriteValue is used as const anyway */
+ UA_Variant_setScalar(&wvalue.value.value,
+ (void*)(uintptr_t)attr, attr_type);
+ } else {
+ wvalue.value.value = *(const UA_Variant*)attr;
+ }
+ return UA_Server_write(server, &wvalue);
+}
+
+/*********************************** amalgamated original file "/home/jvoe/open62541/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
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * Copyright 2014-2017 (c) Julius Pfrommer, Fraunhofer IOSB
+ * Copyright 2014-2016 (c) Sten Grüner
+ * Copyright 2014, 2017 (c) Florian Palm
+ * Copyright 2016 (c) Oleksiy Vasylyev
+ * Copyright 2016-2017 (c) Stefan Profanter, fortiss GmbH
+ * Copyright 2017 (c) frax2222
+ * Copyright 2017 (c) Mark Giraud, Fraunhofer IOSB
+ */
+
+
+#ifdef _WIN32
+# ifndef UNDER_CE
+# include <io.h> //access
+# define access _access
+# endif
+#else
+# include <unistd.h> //access
+#endif
+
+#ifdef UA_ENABLE_DISCOVERY
+
+static UA_StatusCode
+setApplicationDescriptionFromRegisteredServer(const UA_FindServersRequest *request,
+ UA_ApplicationDescription *target,
+ const UA_RegisteredServer *registeredServer) {
+ UA_StatusCode retval = UA_STATUSCODE_GOOD;
+
+ UA_ApplicationDescription_init(target);
+ retval |= UA_String_copy(&registeredServer->serverUri, &target->applicationUri);
+ retval |= UA_String_copy(&registeredServer->productUri, &target->productUri);
+
+ // if the client requests a specific locale, select the corresponding server name
+ if(request->localeIdsSize) {
+ UA_Boolean appNameFound = UA_FALSE;
+ for(size_t i =0; i<request->localeIdsSize && !appNameFound; i++) {
+ for(size_t j =0; j<registeredServer->serverNamesSize; j++) {
+ if(UA_String_equal(&request->localeIds[i], &registeredServer->serverNames[j].locale)) {
+ retval |= UA_LocalizedText_copy(&registeredServer->serverNames[j],
+ &target->applicationName);
+ appNameFound = UA_TRUE;
+ break;
+ }
+ }
+ }
+
+ // server does not have the requested local, therefore we can select the
+ // most suitable one
+ if(!appNameFound && registeredServer->serverNamesSize)
+ retval |= UA_LocalizedText_copy(&registeredServer->serverNames[0],
+ &target->applicationName);
+ } else if(registeredServer->serverNamesSize) {
+ // just take the first name
+ retval |= UA_LocalizedText_copy(&registeredServer->serverNames[0], &target->applicationName);
+ }
+
+ target->applicationType = registeredServer->serverType;
+ retval |= UA_String_copy(&registeredServer->gatewayServerUri, &target->gatewayServerUri);
+ // TODO where do we get the discoveryProfileUri for application data?
+
+ target->discoveryUrlsSize = registeredServer->discoveryUrlsSize;
+ if(registeredServer->discoveryUrlsSize) {
+ size_t duSize = sizeof(UA_String) * registeredServer->discoveryUrlsSize;
+ target->discoveryUrls = (UA_String *)UA_malloc(duSize);
+ if(!target->discoveryUrls)
+ return UA_STATUSCODE_BADOUTOFMEMORY;
+ for(size_t i = 0; i<registeredServer->discoveryUrlsSize; i++)
+ retval |= UA_String_copy(&registeredServer->discoveryUrls[i], &target->discoveryUrls[i]);
+ }
+
+ return retval;
+}
+#endif
+
+static UA_StatusCode
+setApplicationDescriptionFromServer(UA_ApplicationDescription *target, const UA_Server *server) {
+ /* Copy ApplicationDescription from the config */
+
+ UA_StatusCode result = UA_ApplicationDescription_copy(&server->config.applicationDescription,
+ target);
+ if(result != UA_STATUSCODE_GOOD) {
+ return result;
+ }
+ // UaExpert does not list DiscoveryServer, thus set it to Server
+ // See http://forum.unified-automation.com/topic1987.html
+ if(target->applicationType == UA_APPLICATIONTYPE_DISCOVERYSERVER)
+ target->applicationType = UA_APPLICATIONTYPE_SERVER;
+
+ /* add the discoveryUrls from the networklayers */
+ size_t discSize = sizeof(UA_String) * (target->discoveryUrlsSize + server->config.networkLayersSize);
+ UA_String* disc = (UA_String *)UA_realloc(target->discoveryUrls, discSize);
+ if(!disc) {
+ return UA_STATUSCODE_BADOUTOFMEMORY;
+ }
+ size_t existing = target->discoveryUrlsSize;
+ target->discoveryUrls = disc;
+ target->discoveryUrlsSize += server->config.networkLayersSize;
+
+ // TODO: Add nl only if discoveryUrl not already present
+ for(size_t i = 0; i < server->config.networkLayersSize; i++) {
+ UA_ServerNetworkLayer* nl = &server->config.networkLayers[i];
+ UA_String_copy(&nl->discoveryUrl, &target->discoveryUrls[existing + i]);
+ }
+ return UA_STATUSCODE_GOOD;
+}
+
+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");
+
+ size_t foundServersSize = 0;
+ UA_ApplicationDescription *foundServers = NULL;
+
+ UA_Boolean addSelf = UA_FALSE;
+ // temporarily store all the pointers which we found to avoid reiterating
+ // through the list
+ UA_RegisteredServer **foundServerFilteredPointer = NULL;
+
+#ifdef UA_ENABLE_DISCOVERY
+ // check if client only requested a specific set of servers
+ if(request->serverUrisSize) {
+ size_t fsfpSize = sizeof(UA_RegisteredServer*) * server->registeredServersSize;
+ foundServerFilteredPointer = (UA_RegisteredServer **)UA_malloc(fsfpSize);
+ if(!foundServerFilteredPointer) {
+ response->responseHeader.serviceResult = UA_STATUSCODE_BADOUTOFMEMORY;
+ return;
+ }
+
+ for(size_t i = 0; i < request->serverUrisSize; i++) {
+ if(!addSelf && UA_String_equal(&request->serverUris[i],
+ &server->config.applicationDescription.applicationUri)) {
+ addSelf = UA_TRUE;
+ } else {
+ registeredServer_list_entry* current;
+ LIST_FOREACH(current, &server->registeredServers, pointers) {
+ if(UA_String_equal(&current->registeredServer.serverUri, &request->serverUris[i])) {
+ // check if entry already in list:
+ UA_Boolean existing = false;
+ for(size_t j=0; j<foundServersSize; j++) {
+ if(UA_String_equal(&foundServerFilteredPointer[j]->serverUri, &request->serverUris[i])) {
+ existing = true;
+ break;
+ }
+ }
+ if(!existing)
+ foundServerFilteredPointer[foundServersSize++] = &current->registeredServer;
+ break;
+ }
+ }
+ }
+ }
+
+ if(addSelf)
+ foundServersSize++;
+
+ } else {
+ addSelf = true;
+ // self + registered servers
+ foundServersSize = 1 + server->registeredServersSize;
+ }
+#else
+ if(request->serverUrisSize) {
+ for(size_t i = 0; i < request->serverUrisSize; i++) {
+ if(UA_String_equal(&request->serverUris[i],
+ &server->config.applicationDescription.applicationUri)) {
+ addSelf = UA_TRUE;
+ foundServersSize = 1;
+ break;
+ }
+ }
+ } else {
+ addSelf = UA_TRUE;
+ foundServersSize = 1;
+ }
+#endif
+
+ if(foundServersSize) {
+ size_t fsSize = sizeof(UA_ApplicationDescription) * foundServersSize;
+ foundServers = (UA_ApplicationDescription *)UA_malloc(fsSize);
+ if(!foundServers) {
+ if(foundServerFilteredPointer)
+ UA_free(foundServerFilteredPointer);
+ response->responseHeader.serviceResult = UA_STATUSCODE_BADOUTOFMEMORY;
+ return;
+ }
+
+ if(addSelf) {
+ response->responseHeader.serviceResult =
+ setApplicationDescriptionFromServer(&foundServers[0], server);
+ if(response->responseHeader.serviceResult != UA_STATUSCODE_GOOD) {
+ UA_free(foundServers);
+ if(foundServerFilteredPointer)
+ UA_free(foundServerFilteredPointer);
+ return;
+ }
+ }
+
+#ifdef UA_ENABLE_DISCOVERY
+ size_t currentIndex = 0;
+ if(addSelf)
+ currentIndex++;
+
+ // add all the registered servers to the list
+
+ if(foundServerFilteredPointer) {
+ // use filtered list because client only requested specific uris
+ // -1 because foundServersSize also includes this self server
+ size_t iterCount = addSelf ? foundServersSize - 1 : foundServersSize;
+ for(size_t i = 0; i < iterCount; i++) {
+ response->responseHeader.serviceResult =
+ setApplicationDescriptionFromRegisteredServer(request, &foundServers[currentIndex++],
+ foundServerFilteredPointer[i]);
+ if(response->responseHeader.serviceResult != UA_STATUSCODE_GOOD) {
+ UA_free(foundServers);
+ UA_free(foundServerFilteredPointer);
+ return;
+ }
+ }
+ UA_free(foundServerFilteredPointer);
+ foundServerFilteredPointer = NULL;
+ } else {
+ registeredServer_list_entry* current;
+ LIST_FOREACH(current, &server->registeredServers, pointers) {
+ response->responseHeader.serviceResult =
+ setApplicationDescriptionFromRegisteredServer(request, &foundServers[currentIndex++],
+ &current->registeredServer);
+ if(response->responseHeader.serviceResult != UA_STATUSCODE_GOOD) {
+ UA_free(foundServers);
+ return;
+ }
+ }
+ }
+#endif
+ }
+
+ if(foundServerFilteredPointer)
+ UA_free(foundServerFilteredPointer);
+
+ response->servers = foundServers;
+ response->serversSize = foundServersSize;
+}
+
+void Service_GetEndpoints(UA_Server *server, UA_Session *session,
+ const UA_GetEndpointsRequest *request,
+ UA_GetEndpointsResponse *response) {
+ /* If the client expects to see a specific endpointurl, mirror it back. If
+ 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,
+ "Processing GetEndpointsRequest with endpointUrl "
+ UA_PRINTF_STRING_FORMAT, UA_PRINTF_STRING_DATA(*endpointUrl));
+ } else {
+ UA_LOG_DEBUG_SESSION(server->config.logger, 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].endpointDescription.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;
+ if(endpointUrl->length == 0) {
+ clone_times = server->config.networkLayersSize;
+ nl_endpointurl = true;
+ }
+
+ response->endpoints =
+ (UA_EndpointDescription*)UA_Array_new(relevant_count * 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 = UA_STATUSCODE_GOOD;
+ 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].endpointDescription,
+ &response->endpoints[k]);
+ retval |= UA_String_copy(endpointUrl, &response->endpoints[k].endpointUrl);
+ ++k;
+ }
+ }
+
+ if(retval != UA_STATUSCODE_GOOD) {
+ response->responseHeader.serviceResult = retval;
+ UA_Array_delete(response->endpoints, response->endpointsSize,
+ &UA_TYPES[UA_TYPES_ENDPOINTDESCRIPTION]);
+ response->endpoints = NULL;
+ response->endpointsSize = 0;
+ return;
+ }
+}
+
+#ifdef UA_ENABLE_DISCOVERY
+
+#ifdef UA_ENABLE_MULTITHREADING
+static void
+freeEntry(UA_Server *server, void *entry) {
+ UA_free(entry);
+}
+#endif
+
+static void
+process_RegisterServer(UA_Server *server, UA_Session *session,
+ const UA_RequestHeader* requestHeader,
+ const UA_RegisteredServer *requestServer,
+ const size_t requestDiscoveryConfigurationSize,
+ const UA_ExtensionObject *requestDiscoveryConfiguration,
+ UA_ResponseHeader* responseHeader,
+ size_t *responseConfigurationResultsSize,
+ UA_StatusCode **responseConfigurationResults,
+ size_t *responseDiagnosticInfosSize,
+ UA_DiagnosticInfo *responseDiagnosticInfos) {
+ /* Find the server from the request in the registered list */
+ registeredServer_list_entry* current;
+ registeredServer_list_entry *registeredServer_entry = NULL;
+ LIST_FOREACH(current, &server->registeredServers, pointers) {
+ if(UA_String_equal(&current->registeredServer.serverUri, &requestServer->serverUri)) {
+ registeredServer_entry = current;
+ break;
+ }
+ }
+
+ UA_MdnsDiscoveryConfiguration *mdnsConfig = NULL;
+
+ const UA_String* mdnsServerName = NULL;
+ if(requestDiscoveryConfigurationSize) {
+ *responseConfigurationResults =
+ (UA_StatusCode *)UA_Array_new(requestDiscoveryConfigurationSize,
+ &UA_TYPES[UA_TYPES_STATUSCODE]);
+ if(!(*responseConfigurationResults)) {
+ responseHeader->serviceResult = UA_STATUSCODE_BADOUTOFMEMORY;
+ return;
+ }
+ *responseConfigurationResultsSize = requestDiscoveryConfigurationSize;
+
+ for(size_t i = 0; i < requestDiscoveryConfigurationSize; i++) {
+ const UA_ExtensionObject *object = &requestDiscoveryConfiguration[i];
+ if(!mdnsConfig && (object->encoding == UA_EXTENSIONOBJECT_DECODED ||
+ object->encoding == UA_EXTENSIONOBJECT_DECODED_NODELETE) &&
+ (object->content.decoded.type == &UA_TYPES[UA_TYPES_MDNSDISCOVERYCONFIGURATION])) {
+ mdnsConfig = (UA_MdnsDiscoveryConfiguration *)object->content.decoded.data;
+ mdnsServerName = &mdnsConfig->mdnsServerName;
+ (*responseConfigurationResults)[i] = UA_STATUSCODE_GOOD;
+ } else {
+ (*responseConfigurationResults)[i] = UA_STATUSCODE_BADNOTSUPPORTED;
+ }
+ }
+ }
+
+ if(!mdnsServerName && requestServer->serverNamesSize)
+ mdnsServerName = &requestServer->serverNames[0].text;
+
+ if(!mdnsServerName) {
+ responseHeader->serviceResult = UA_STATUSCODE_BADSERVERNAMEMISSING;
+ return;
+ }
+
+ if(requestServer->discoveryUrlsSize == 0) {
+ responseHeader->serviceResult = UA_STATUSCODE_BADDISCOVERYURLMISSING;
+ return;
+ }
+
+ if(requestServer->semaphoreFilePath.length) {
+#ifdef UA_ENABLE_DISCOVERY_SEMAPHORE
+ char* filePath = (char*)
+ UA_malloc(sizeof(char)*requestServer->semaphoreFilePath.length+1);
+ if(!filePath) {
+ UA_LOG_ERROR_SESSION(server->config.logger, session,
+ "Cannot allocate memory for semaphore path. Out of memory.");
+ responseHeader->serviceResult = UA_STATUSCODE_BADOUTOFMEMORY;
+ return;
+ }
+ memcpy(filePath, requestServer->semaphoreFilePath.data, requestServer->semaphoreFilePath.length );
+ filePath[requestServer->semaphoreFilePath.length] = '\0';
+ if(access( filePath, 0 ) == -1) {
+ responseHeader->serviceResult = UA_STATUSCODE_BADSEMPAHOREFILEMISSING;
+ UA_free(filePath);
+ return;
+ }
+ UA_free(filePath);
+#else
+ UA_LOG_WARNING(server->config.logger, UA_LOGCATEGORY_CLIENT,
+ "Ignoring semaphore file path. open62541 not compiled "
+ "with UA_ENABLE_DISCOVERY_SEMAPHORE=ON");
+#endif
+ }
+
+#ifdef UA_ENABLE_DISCOVERY_MULTICAST
+ if(server->config.applicationDescription.applicationType == UA_APPLICATIONTYPE_DISCOVERYSERVER) {
+ 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) ||
+ (!requestServer->isOnline && i==requestServer->discoveryUrlsSize);
+ UA_Discovery_update_MdnsForDiscoveryUrl(server, mdnsServerName, mdnsConfig,
+ &requestServer->discoveryUrls[i],
+ requestServer->isOnline, updateTxt);
+ }
+ }
+#endif
+
+ if(!requestServer->isOnline) {
+ // server is shutting down. Remove it from the registered servers list
+ if(!registeredServer_entry) {
+ // server not found, show warning
+ UA_LOG_WARNING_SESSION(server->config.logger, session,
+ "Could not unregister server %.*s. Not registered.",
+ (int)requestServer->serverUri.length, requestServer->serverUri.data);
+ responseHeader->serviceResult = UA_STATUSCODE_BADNOTHINGTODO;
+ return;
+ }
+
+ if(server->registerServerCallback)
+ server->registerServerCallback(requestServer, server->registerServerCallbackData);
+
+ // server found, remove from list
+ LIST_REMOVE(registeredServer_entry, pointers);
+ UA_RegisteredServer_deleteMembers(&registeredServer_entry->registeredServer);
+#ifndef UA_ENABLE_MULTITHREADING
+ UA_free(registeredServer_entry);
+ server->registeredServersSize--;
+#else
+ UA_atomic_subSize(&server->registeredServersSize, 1);
+ UA_Server_delayedCallback(server, freeEntry, registeredServer_entry);
+#endif
+ responseHeader->serviceResult = UA_STATUSCODE_GOOD;
+ return;
+ }
+
+ UA_StatusCode retval = UA_STATUSCODE_GOOD;
+ if(!registeredServer_entry) {
+ // server not yet registered, register it by adding it to the list
+ UA_LOG_DEBUG_SESSION(server->config.logger, session, "Registering new server: %.*s",
+ (int)requestServer->serverUri.length, requestServer->serverUri.data);
+
+ registeredServer_entry =
+ (registeredServer_list_entry *)UA_malloc(sizeof(registeredServer_list_entry));
+ if(!registeredServer_entry) {
+ responseHeader->serviceResult = UA_STATUSCODE_BADOUTOFMEMORY;
+ return;
+ }
+
+ LIST_INSERT_HEAD(&server->registeredServers, registeredServer_entry, pointers);
+#ifndef UA_ENABLE_MULTITHREADING
+ server->registeredServersSize++;
+#else
+ UA_atomic_addSize(&server->registeredServersSize, 1);
+#endif
+
+ if(server->registerServerCallback)
+ server->registerServerCallback(requestServer, server->registerServerCallbackData);
+ } else {
+ UA_RegisteredServer_deleteMembers(&registeredServer_entry->registeredServer);
+ }
+
+ // copy the data from the request into the list
+ UA_RegisteredServer_copy(requestServer, &registeredServer_entry->registeredServer);
+ registeredServer_entry->lastSeen = UA_DateTime_nowMonotonic();
+ responseHeader->serviceResult = retval;
+}
+
+void Service_RegisterServer(UA_Server *server, UA_Session *session,
+ const UA_RegisterServerRequest *request,
+ UA_RegisterServerResponse *response) {
+ UA_LOG_DEBUG_SESSION(server->config.logger, session,
+ "Processing RegisterServerRequest");
+ process_RegisterServer(server, session, &request->requestHeader, &request->server, 0,
+ NULL, &response->responseHeader, 0, NULL, 0, NULL);
+}
+
+void Service_RegisterServer2(UA_Server *server, UA_Session *session,
+ const UA_RegisterServer2Request *request,
+ UA_RegisterServer2Response *response) {
+ UA_LOG_DEBUG_SESSION(server->config.logger, session,
+ "Processing RegisterServer2Request");
+ process_RegisterServer(server, session, &request->requestHeader, &request->server,
+ request->discoveryConfigurationSize, request->discoveryConfiguration,
+ &response->responseHeader, &response->configurationResultsSize,
+ &response->configurationResults, &response->diagnosticInfosSize,
+ response->diagnosticInfos);
+}
+
+/* Cleanup server registration: If the semaphore file path is set, then it just
+ * checks the existence of the file. When it is deleted, the registration is
+ * removed. If there is no semaphore file, then the registration will be removed
+ * if it is older than 60 minutes. */
+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.discoveryCleanupTimeout)
+ timedOut -= server->config.discoveryCleanupTimeout*UA_DATETIME_SEC;
+
+ registeredServer_list_entry* current, *temp;
+ LIST_FOREACH_SAFE(current, &server->registeredServers, pointers, temp) {
+ UA_Boolean semaphoreDeleted = UA_FALSE;
+
+#ifdef UA_ENABLE_DISCOVERY_SEMAPHORE
+ if(current->registeredServer.semaphoreFilePath.length) {
+ size_t fpSize = sizeof(char)*current->registeredServer.semaphoreFilePath.length+1;
+ // todo: malloc may fail: return a statuscode
+ char* filePath = (char *)UA_malloc(fpSize);
+ if(filePath) {
+ memcpy(filePath, current->registeredServer.semaphoreFilePath.data,
+ current->registeredServer.semaphoreFilePath.length );
+ filePath[current->registeredServer.semaphoreFilePath.length] = '\0';
+#ifdef UNDER_CE
+ FILE *fp = fopen(filePath,"rb");
+ semaphoreDeleted = (fp==NULL);
+ if(fp)
+ fclose(fp);
+#else
+ semaphoreDeleted = access( filePath, 0 ) == -1;
+#endif
+ UA_free(filePath);
+ } else {
+ UA_LOG_ERROR(server->config.logger, UA_LOGCATEGORY_SERVER, "Cannot check registration semaphore. Out of memory");
+ }
+ }
+#endif
+
+ if(semaphoreDeleted || (server->config.discoveryCleanupTimeout &&
+ current->lastSeen < timedOut)) {
+ if(semaphoreDeleted) {
+ UA_LOG_INFO(server->config.logger, UA_LOGCATEGORY_SERVER,
+ "Registration of server with URI %.*s is removed because "
+ "the semaphore file '%.*s' was deleted.",
+ (int)current->registeredServer.serverUri.length,
+ current->registeredServer.serverUri.data,
+ (int)current->registeredServer.semaphoreFilePath.length,
+ current->registeredServer.semaphoreFilePath.data);
+ } else {
+ // cppcheck-suppress unreadVariable
+ UA_LOG_INFO(server->config.logger, UA_LOGCATEGORY_SERVER,
+ "Registration of server with URI %.*s has timed out and is removed.",
+ (int)current->registeredServer.serverUri.length,
+ current->registeredServer.serverUri.data);
+ }
+ LIST_REMOVE(current, pointers);
+ UA_RegisteredServer_deleteMembers(&current->registeredServer);
+#ifndef UA_ENABLE_MULTITHREADING
+ UA_free(current);
+ server->registeredServersSize--;
+#else
+ UA_atomic_subSize(&server->registeredServersSize, 1);
+ UA_Server_delayedCallback(server, freeEntry, current);
+#endif
+ }
+ }
+}
+
+struct PeriodicServerRegisterCallback {
+ UA_UInt64 id;
+ UA_UInt32 this_interval;
+ UA_UInt32 default_interval;
+ UA_Boolean registered;
+ const char* discovery_server_url;
+};
+
+/* Called by the UA_Server callback. The OPC UA specification says:
+ *
+ * > If an error occurs during registration (e.g. the Discovery Server is not running) then the Server
+ * > must periodically re-attempt registration. The frequency of these attempts should start at 1 second
+ * > but gradually increase until the registration frequency is the same as what it would be if not
+ * > errors occurred. The recommended approach would double the period each attempt until reaching the maximum.
+ *
+ * We will do so by using the additional data parameter which holds information
+ * if the next interval is default or if it is a repeaded call. */
+static void
+periodicServerRegister(UA_Server *server, void *data) {
+ UA_assert(data != NULL);
+
+ struct PeriodicServerRegisterCallback *cb = (struct PeriodicServerRegisterCallback *)data;
+
+ /* Which URL to register on */
+ // fixme: remove magic url
+ const char * server_url;
+ if(cb->discovery_server_url != NULL)
+ server_url = cb->discovery_server_url;
+ else
+ server_url = "opc.tcp://localhost:4840";
+
+ /* Register
+ You can also use a semaphore file. That file must exist. When the file is
+ deleted, the server is automatically unregistered. The semaphore file has
+ to be accessible by the discovery server
+
+ UA_StatusCode retval = UA_Server_register_discovery(server,
+ "opc.tcp://localhost:4840", "/path/to/some/file");
+ */
+ UA_StatusCode retval = UA_Server_register_discovery(server, server_url, NULL);
+
+ /* Registering failed */
+ if(retval != UA_STATUSCODE_GOOD) {
+ UA_LOG_ERROR(server->config.logger, UA_LOGCATEGORY_SERVER,
+ "Could not register server with discovery server. "
+ "Is the discovery server started? StatusCode %s",
+ UA_StatusCode_name(retval));
+
+ /* If the server was previously registered, retry in one second,
+ * else, double the previous interval */
+ UA_UInt32 nextInterval = 1000;
+ if(!cb->registered)
+ nextInterval = cb->this_interval * 2;
+
+ /* The interval should be smaller than the default interval */
+ if(nextInterval > cb->default_interval)
+ nextInterval = cb->default_interval;
+
+ cb->this_interval = nextInterval;
+ UA_Server_changeRepeatedCallbackInterval(server, cb->id, nextInterval);
+ return;
+ }
+
+ /* Registering succeeded */
+ UA_LOG_DEBUG(server->config.logger, UA_LOGCATEGORY_SERVER,
+ "Server successfully registered. Next periodical register will be in %d seconds",
+ (int)(cb->default_interval/1000));
+
+ if(!cb->registered) {
+ retval = UA_Server_changeRepeatedCallbackInterval(server, cb->id, cb->default_interval);
+ /* If changing the interval fails, try again after the next registering */
+ if(retval == UA_STATUSCODE_GOOD)
+ cb->registered = true;
+ }
+}
+
+UA_StatusCode
+UA_Server_addPeriodicServerRegisterCallback(UA_Server *server,
+ const char* discoveryServerUrl,
+ UA_UInt32 intervalMs,
+ UA_UInt32 delayFirstRegisterMs,
+ UA_UInt64 *periodicCallbackId) {
+
+ /* No valid server URL */
+ if(!discoveryServerUrl) {
+ UA_LOG_ERROR(server->config.logger, UA_LOGCATEGORY_SERVER,
+ "No discovery server URL provided");
+ return UA_STATUSCODE_BADINTERNALERROR;
+ }
+
+
+ /* check if we are already registering with the given discovery url and remove the old periodic call */
+ {
+ periodicServerRegisterCallback_entry *rs, *rs_tmp;
+ LIST_FOREACH_SAFE(rs, &server->periodicServerRegisterCallbacks, pointers, rs_tmp) {
+ if(strcmp(rs->callback->discovery_server_url, discoveryServerUrl) == 0) {
+ UA_LOG_INFO(server->config.logger, UA_LOGCATEGORY_SERVER,
+ "There is already a register callback for '%s' in place. Removing the older one.", discoveryServerUrl);
+ UA_Server_removeRepeatedCallback(server, rs->callback->id);
+ LIST_REMOVE(rs, pointers);
+ UA_free(rs->callback);
+ UA_free(rs);
+ break;
+ }
+ }
+ }
+
+ /* Allocate and initialize */
+ struct PeriodicServerRegisterCallback* cb =
+ (struct PeriodicServerRegisterCallback*)
+ UA_malloc(sizeof(struct PeriodicServerRegisterCallback));
+ if(!cb)
+ return UA_STATUSCODE_BADOUTOFMEMORY;
+
+ /* Start repeating a failed register after 1s, then increase the delay. Set
+ * to 500ms, as the delay is doubled before changing the callback
+ * interval.*/
+ cb->this_interval = 500;
+ cb->default_interval = intervalMs;
+ cb->registered = false;
+ cb->discovery_server_url = discoveryServerUrl;
+
+
+
+ /* Add the callback */
+ UA_StatusCode retval =
+ UA_Server_addRepeatedCallback(server, periodicServerRegister,
+ cb, delayFirstRegisterMs, &cb->id);
+ if(retval != UA_STATUSCODE_GOOD) {
+ UA_LOG_ERROR(server->config.logger, UA_LOGCATEGORY_SERVER,
+ "Could not create periodic job for server register. "
+ "StatusCode %s", UA_StatusCode_name(retval));
+ UA_free(cb);
+ return retval;
+ }
+
+#ifndef __clang_analyzer__
+ // the analyzer reports on LIST_INSERT_HEAD a use after free false positive
+ periodicServerRegisterCallback_entry *newEntry =
+ (periodicServerRegisterCallback_entry *)UA_malloc(sizeof(periodicServerRegisterCallback_entry));
+ if(!newEntry) {
+ UA_Server_removeRepeatedCallback(server, cb->id);
+ UA_free(cb);
+ return UA_STATUSCODE_BADOUTOFMEMORY;
+ }
+ newEntry->callback = cb;
+ LIST_INSERT_HEAD(&server->periodicServerRegisterCallbacks, newEntry, pointers);
+#endif
+
+ if(periodicCallbackId)
+ *periodicCallbackId = cb->id;
+ return UA_STATUSCODE_GOOD;
+}
+
+void
+UA_Server_setRegisterServerCallback(UA_Server *server,
+ UA_Server_registerServerCallback cb,
+ void* data) {
+ server->registerServerCallback = cb;
+ server->registerServerCallbackData = data;
+}
+
+#endif /* UA_ENABLE_DISCOVERY */
+
+/*********************************** amalgamated original file "/home/jvoe/open62541/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-2017 (c) Julius Pfrommer, Fraunhofer IOSB
+ * Copyright 2016-2017 (c) Florian Palm
+ * Copyright 2015 (c) Chris Iatrou
+ * Copyright 2015-2016 (c) Sten Grüner
+ * Copyright 2015-2016 (c) Oleksiy Vasylyev
+ * Copyright 2017 (c) Stefan Profanter, fortiss GmbH
+ * Copyright 2017 (c) Mattias Bornhager
+ * Copyright 2017 (c) Henrik Norrman
+ * Copyright 2017-2018 (c) Thomas Stalder, Blue Time Concept SA
+ */
+
+
+#ifdef UA_ENABLE_SUBSCRIPTIONS /* conditional compilation */
+
+#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; \
+ }
+
+static UA_StatusCode
+setSubscriptionSettings(UA_Server *server, UA_Subscription *subscription,
+ UA_Double requestedPublishingInterval,
+ UA_UInt32 requestedLifetimeCount,
+ UA_UInt32 requestedMaxKeepAliveCount,
+ UA_UInt32 maxNotificationsPerPublish, UA_Byte priority) {
+ /* deregister the callback if required */
+ UA_StatusCode retval = Subscription_unregisterPublishCallback(server, subscription);
+ if(retval != UA_STATUSCODE_GOOD) {
+ UA_LOG_DEBUG_SESSION(server->config.logger, subscription->session,
+ "Subscription %u | Could not unregister publish callback with error code %s",
+ subscription->subscriptionId, UA_StatusCode_name(retval));
+ return retval;
+ }
+
+ /* re-parameterize the subscription */
+ subscription->publishingInterval = requestedPublishingInterval;
+ UA_BOUNDEDVALUE_SETWBOUNDS(server->config.publishingIntervalLimits,
+ requestedPublishingInterval, subscription->publishingInterval);
+ /* check for nan*/
+ if(requestedPublishingInterval != requestedPublishingInterval)
+ subscription->publishingInterval = server->config.publishingIntervalLimits.min;
+ UA_BOUNDEDVALUE_SETWBOUNDS(server->config.keepAliveCountLimits,
+ requestedMaxKeepAliveCount, subscription->maxKeepAliveCount);
+ UA_BOUNDEDVALUE_SETWBOUNDS(server->config.lifeTimeCountLimits,
+ requestedLifetimeCount, subscription->lifeTimeCount);
+ if(subscription->lifeTimeCount < 3 * subscription->maxKeepAliveCount)
+ subscription->lifeTimeCount = 3 * subscription->maxKeepAliveCount;
+ subscription->notificationsPerPublish = maxNotificationsPerPublish;
+ if(maxNotificationsPerPublish == 0 ||
+ maxNotificationsPerPublish > server->config.maxNotificationsPerPublish)
+ subscription->notificationsPerPublish = server->config.maxNotificationsPerPublish;
+ subscription->priority = priority;
+
+ retval = Subscription_registerPublishCallback(server, subscription);
+ if(retval != UA_STATUSCODE_GOOD) {
+ UA_LOG_DEBUG_SESSION(server->config.logger, subscription->session,
+ "Subscription %u | Could not register publish callback with error code %s",
+ subscription->subscriptionId, UA_StatusCode_name(retval));
+ return retval;
+ }
+ return UA_STATUSCODE_GOOD;
+}
+
+void
+Service_CreateSubscription(UA_Server *server, UA_Session *session,
+ const UA_CreateSubscriptionRequest *request,
+ UA_CreateSubscriptionResponse *response) {
+ /* Check limits for the number of subscriptions */
+ if((server->config.maxSubscriptionsPerSession != 0) &&
+ (session->numSubscriptions >= 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_LOG_DEBUG_SESSION(server->config.logger, session,
+ "Processing CreateSubscriptionRequest failed");
+ response->responseHeader.serviceResult = UA_STATUSCODE_BADOUTOFMEMORY;
+ return;
+ }
+
+ UA_Session_addSubscription(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);
+
+ if(retval != UA_STATUSCODE_GOOD) {
+ response->responseHeader.serviceResult = retval;
+ return;
+ }
+
+ newSubscription->currentKeepAliveCount = newSubscription->maxKeepAliveCount; /* set settings first */
+
+ /* Prepare the response */
+ response->subscriptionId = newSubscription->subscriptionId;
+ response->revisedPublishingInterval = newSubscription->publishingInterval;
+ response->revisedLifetimeCount = newSubscription->lifeTimeCount;
+ response->revisedMaxKeepAliveCount = newSubscription->maxKeepAliveCount;
+
+ UA_LOG_INFO_SESSION(server->config.logger, session, "Subscription %u | "
+ "Created the Subscription with a publishing interval of %f ms",
+ response->subscriptionId, newSubscription->publishingInterval);
+}
+
+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_Subscription *sub = UA_Session_getSubscriptionById(session, request->subscriptionId);
+ if(!sub) {
+ response->responseHeader.serviceResult = UA_STATUSCODE_BADSUBSCRIPTIONIDINVALID;
+ return;
+ }
+
+ UA_StatusCode retval = setSubscriptionSettings(server, sub, request->requestedPublishingInterval,
+ request->requestedLifetimeCount, request->requestedMaxKeepAliveCount,
+ request->maxNotificationsPerPublish, request->priority);
+
+ if(retval != UA_STATUSCODE_GOOD) {
+ response->responseHeader.serviceResult = retval;
+ return;
+ }
+
+ sub->currentLifetimeCount = 0; /* Reset the subscription lifetime */
+ response->revisedPublishingInterval = sub->publishingInterval;
+ response->revisedLifetimeCount = sub->lifeTimeCount;
+ response->revisedMaxKeepAliveCount = sub->maxKeepAliveCount;
+}
+
+static void
+Operation_SetPublishingMode(UA_Server *Server, UA_Session *session,
+ UA_Boolean *publishingEnabled, UA_UInt32 *subscriptionId,
+ UA_StatusCode *result) {
+ UA_Subscription *sub = UA_Session_getSubscriptionById(session, *subscriptionId);
+ if(!sub) {
+ *result = UA_STATUSCODE_BADSUBSCRIPTIONIDINVALID;
+ return;
+ }
+
+ sub->currentLifetimeCount = 0; /* Reset the subscription lifetime */
+ sub->publishingEnabled = *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_Boolean publishingEnabled = request->publishingEnabled; /* request is const */
+ response->responseHeader.serviceResult =
+ UA_Server_processServiceOperations(server, session, (UA_ServiceOperation)Operation_SetPublishingMode,
+ &publishingEnabled,
+ &request->subscriptionIdsSize, &UA_TYPES[UA_TYPES_UINT32],
+ &response->resultsSize, &UA_TYPES[UA_TYPES_STATUSCODE]);
+}
+
+static UA_StatusCode
+setMonitoredItemSettings(UA_Server *server, UA_MonitoredItem *mon,
+ UA_MonitoringMode monitoringMode,
+ const UA_MonitoringParameters *params,
+ // This parameter is optional and used only if mon->lastValue is not set yet.
+ // Then numeric type will be detected from this value. Set null as defaut.
+ const UA_DataType* dataType) {
+
+ /* Filter */
+ if(params->filter.encoding != UA_EXTENSIONOBJECT_DECODED) {
+ UA_DataChangeFilter_init(&(mon->filter));
+ mon->filter.trigger = UA_DATACHANGETRIGGER_STATUSVALUE;
+ } else if(params->filter.content.decoded.type != &UA_TYPES[UA_TYPES_DATACHANGEFILTER]) {
+ return UA_STATUSCODE_BADMONITOREDITEMFILTERINVALID;
+ } else {
+ UA_DataChangeFilter *filter = (UA_DataChangeFilter *)params->filter.content.decoded.data;
+ // TODO implement EURange to support UA_DEADBANDTYPE_PERCENT
+ if (filter->deadbandType == UA_DEADBANDTYPE_PERCENT) {
+ return UA_STATUSCODE_BADMONITOREDITEMFILTERUNSUPPORTED;
+ }
+ if (UA_Variant_isEmpty(&mon->lastValue)) {
+ if (!dataType || !isDataTypeNumeric(dataType))
+ return UA_STATUSCODE_BADFILTERNOTALLOWED;
+ } else
+ if (!isDataTypeNumeric(mon->lastValue.type)) {
+ return UA_STATUSCODE_BADFILTERNOTALLOWED;
+ }
+ UA_DataChangeFilter_copy(filter, &(mon->filter));
+ }
+
+ MonitoredItem_unregisterSampleCallback(server, mon);
+ mon->monitoringMode = monitoringMode;
+
+ /* ClientHandle */
+ mon->clientHandle = params->clientHandle;
+
+ /* SamplingInterval */
+ UA_Double samplingInterval = params->samplingInterval;
+ 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);
+ }
+ } else if(mon->attributeId == UA_ATTRIBUTEID_EVENTNOTIFIER) {
+ /* TODO: events should not need a samplinginterval */
+ samplingInterval = 10000.0f; // 10 seconds to reduce the load
+ }
+ mon->samplingInterval = samplingInterval;
+ UA_BOUNDEDVALUE_SETWBOUNDS(server->config.samplingIntervalLimits,
+ samplingInterval, mon->samplingInterval);
+ if(samplingInterval != samplingInterval) /* Check for nan */
+ mon->samplingInterval = server->config.samplingIntervalLimits.min;
+
+
+ /* QueueSize */
+ UA_BOUNDEDVALUE_SETWBOUNDS(server->config.queueSizeLimits,
+ params->queueSize, mon->maxQueueSize);
+
+ /* DiscardOldest */
+ mon->discardOldest = params->discardOldest;
+
+ /* Register sample callback if reporting is enabled */
+ if(monitoringMode == UA_MONITORINGMODE_REPORTING)
+ return MonitoredItem_registerSampleCallback(server, mon);
+
+ return UA_STATUSCODE_GOOD;
+}
+
+static const UA_String binaryEncoding = {sizeof("Default Binary") - 1, (UA_Byte *)"Default Binary"};
+
+/* Thread-local variables to pass additional arguments into the operation */
+struct createMonContext {
+ UA_Subscription *sub;
+ UA_TimestampsToReturn timestampsToReturn;
+};
+
+static void
+Operation_CreateMonitoredItem(UA_Server *server, UA_Session *session, struct createMonContext *cmc,
+ const UA_MonitoredItemCreateRequest *request,
+ UA_MonitoredItemCreateResult *result) {
+ /* Check available capacity */
+ if(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_deleteMembers(&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_deleteMembers(&v);
+ return;
+ }
+
+ /* Check if the encoding is set for a value */
+ if(request->itemToMonitor.attributeId != UA_ATTRIBUTEID_VALUE &&
+ request->itemToMonitor.dataEncoding.name.length > 0) {
+ result->statusCode = UA_STATUSCODE_BADDATAENCODINGINVALID;
+ UA_DataValue_deleteMembers(&v);
+ return;
+ }
+
+ /* Create the monitoreditem */
+ UA_MonitoredItem *newMon = UA_MonitoredItem_new(UA_MONITOREDITEMTYPE_CHANGENOTIFY);
+ if(!newMon) {
+ result->statusCode = UA_STATUSCODE_BADOUTOFMEMORY;
+ UA_DataValue_deleteMembers(&v);
+ return;
+ }
+ UA_StatusCode retval = UA_NodeId_copy(&request->itemToMonitor.nodeId,
+ &newMon->monitoredNodeId);
+ if(retval != UA_STATUSCODE_GOOD) {
+ result->statusCode = retval;
+ MonitoredItem_delete(server, newMon);
+ UA_DataValue_deleteMembers(&v);
+ return;
+ }
+ newMon->subscription = cmc->sub;
+ newMon->attributeId = request->itemToMonitor.attributeId;
+ UA_String_copy(&request->itemToMonitor.indexRange, &newMon->indexRange);
+ newMon->monitoredItemId = ++cmc->sub->lastMonitoredItemId;
+ newMon->timestampsToReturn = cmc->timestampsToReturn;
+ retval = setMonitoredItemSettings(server, newMon, request->monitoringMode,
+ &request->requestedParameters, v.value.type);
+ UA_DataValue_deleteMembers(&v);
+ if(retval != UA_STATUSCODE_GOOD) {
+ UA_LOG_INFO_SESSION(server->config.logger, cmc->sub->session,
+ "Subscription %u | Could not create a MonitoredItem "
+ "with StatusCode %s", cmc->sub->subscriptionId,
+ UA_StatusCode_name(retval));
+ result->statusCode = retval;
+ MonitoredItem_delete(server, newMon);
+ --cmc->sub->lastMonitoredItemId;
+ return;
+ }
+
+ UA_Subscription_addMonitoredItem(cmc->sub, newMon);
+ UA_LOG_INFO_SESSION(server->config.logger, cmc->sub->session,
+ "Subscription %u | MonitoredItem %i | "
+ "Created the MonitoredItem", cmc->sub->subscriptionId,
+ newMon->monitoredItemId);
+
+ /* Create the first sample */
+ if(request->monitoringMode == UA_MONITORINGMODE_REPORTING)
+ UA_MonitoredItem_SampleCallback(server, newMon);
+
+ /* Prepare the response */
+ result->revisedSamplingInterval = newMon->samplingInterval;
+ result->revisedQueueSize = newMon->maxQueueSize;
+ result->monitoredItemId = newMon->monitoredItemId;
+}
+
+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");
+
+ if(server->config.maxMonitoredItemsPerCall != 0 &&
+ request->itemsToCreateSize > server->config.maxMonitoredItemsPerCall) {
+ response->responseHeader.serviceResult = UA_STATUSCODE_BADTOOMANYOPERATIONS;
+ return;
+ }
+
+ /* Check if the timestampstoreturn is valid */
+ struct createMonContext cmc;
+ cmc.timestampsToReturn = request->timestampsToReturn;
+ if(cmc.timestampsToReturn > UA_TIMESTAMPSTORETURN_NEITHER) {
+ response->responseHeader.serviceResult = UA_STATUSCODE_BADTIMESTAMPSTORETURNINVALID;
+ return;
+ }
+
+ /* Find the subscription */
+ cmc.sub = UA_Session_getSubscriptionById(session, request->subscriptionId);
+ if(!cmc.sub) {
+ response->responseHeader.serviceResult = UA_STATUSCODE_BADSUBSCRIPTIONIDINVALID;
+ return;
+ }
+
+ /* Reset the subscription lifetime */
+ 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]);
+}
+
+static void
+Operation_ModifyMonitoredItem(UA_Server *server, UA_Session *session, UA_Subscription *sub,
+ const UA_MonitoredItemModifyRequest *request,
+ UA_MonitoredItemModifyResult *result) {
+ /* Get the MonitoredItem */
+ UA_MonitoredItem *mon = UA_Subscription_getMonitoredItem(sub, request->monitoredItemId);
+ if(!mon) {
+ result->statusCode = UA_STATUSCODE_BADMONITOREDITEMIDINVALID;
+ return;
+ }
+ UA_StatusCode retval;
+ retval = setMonitoredItemSettings(server, mon, mon->monitoringMode, &request->requestedParameters, NULL);
+ if(retval != UA_STATUSCODE_GOOD) {
+ result->statusCode = retval;
+ return;
+ }
+
+ result->revisedSamplingInterval = mon->samplingInterval;
+ result->revisedQueueSize = mon->maxQueueSize;
+
+ /* Remove some notifications if the queue is now too small */
+ MonitoredItem_ensureQueueSpace(mon);
+}
+
+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");
+
+ if(server->config.maxMonitoredItemsPerCall != 0 &&
+ request->itemsToModifySize > server->config.maxMonitoredItemsPerCall) {
+ response->responseHeader.serviceResult = UA_STATUSCODE_BADTOOMANYOPERATIONS;
+ return;
+ }
+
+ /* Check if the timestampstoreturn is valid */
+ if(request->timestampsToReturn > UA_TIMESTAMPSTORETURN_NEITHER) {
+ response->responseHeader.serviceResult = UA_STATUSCODE_BADTIMESTAMPSTORETURNINVALID;
+ return;
+ }
+
+ /* Get the subscription */
+ UA_Subscription *sub = UA_Session_getSubscriptionById(session, request->subscriptionId);
+ if(!sub) {
+ response->responseHeader.serviceResult = UA_STATUSCODE_BADSUBSCRIPTIONIDINVALID;
+ return;
+ }
+
+ sub->currentLifetimeCount = 0; /* Reset the subscription lifetime */
+
+ 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]);
+}
+
+struct setMonitoringContext {
+ UA_Subscription *sub;
+ UA_MonitoringMode monitoringMode;
+};
+
+static void
+Operation_SetMonitoringMode(UA_Server *server, UA_Session *session,
+ struct setMonitoringContext *smc,
+ UA_UInt32 *monitoredItemId, UA_StatusCode *result) {
+ UA_MonitoredItem *mon = UA_Subscription_getMonitoredItem(smc->sub, *monitoredItemId);
+ if(!mon) {
+ *result = UA_STATUSCODE_BADMONITOREDITEMIDINVALID;
+ return;
+ }
+
+ if(mon->monitoredItemType != UA_MONITOREDITEMTYPE_CHANGENOTIFY) {
+ *result = UA_STATUSCODE_BADNOTIMPLEMENTED;
+ return;
+ }
+
+ /* Check if the MonitoringMode is valid or not */
+ if(smc->monitoringMode > UA_MONITORINGMODE_REPORTING) {
+ *result = UA_STATUSCODE_BADMONITORINGMODEINVALID;
+ return;
+ }
+
+ if(mon->monitoringMode == smc->monitoringMode)
+ return;
+
+ mon->monitoringMode = smc->monitoringMode;
+ if(mon->monitoringMode == UA_MONITORINGMODE_REPORTING) {
+ *result = MonitoredItem_registerSampleCallback(server, mon);
+ } else {
+ MonitoredItem_unregisterSampleCallback(server, mon);
+
+ // TODO correctly implement SAMPLING
+ /* 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) {
+ TAILQ_REMOVE(&mon->queue, notification, listEntry);
+ TAILQ_REMOVE(&smc->sub->notificationQueue, notification, globalEntry);
+ --smc->sub->notificationQueueSize;
+
+ UA_DataValue_deleteMembers(&notification->data.value);
+ UA_free(notification);
+ }
+ mon->queueSize = 0;
+
+ /* Initialize lastSampledValue */
+ UA_ByteString_deleteMembers(&mon->lastSampledValue);
+ UA_Variant_deleteMembers(&mon->lastValue);
+ }
+}
+
+void
+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");
+
+ if(server->config.maxMonitoredItemsPerCall != 0 &&
+ request->monitoredItemIdsSize > server->config.maxMonitoredItemsPerCall) {
+ response->responseHeader.serviceResult = UA_STATUSCODE_BADTOOMANYOPERATIONS;
+ return;
+ }
+
+ /* Get the subscription */
+ struct setMonitoringContext smc;
+ smc.sub = UA_Session_getSubscriptionById(session, request->subscriptionId);
+ if(!smc.sub) {
+ response->responseHeader.serviceResult = UA_STATUSCODE_BADSUBSCRIPTIONIDINVALID;
+ return;
+ }
+
+ smc.sub->currentLifetimeCount = 0; /* Reset the subscription lifetime */
+
+ 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]);
+}
+
+/* TODO: Unify with senderror in ua_server_binary.c */
+static void
+subscriptionSendError(UA_SecureChannel *channel, UA_UInt32 requestHandle,
+ UA_UInt32 requestId, UA_StatusCode error) {
+ UA_PublishResponse err_response;
+ UA_PublishResponse_init(&err_response);
+ err_response.responseHeader.requestHandle = requestHandle;
+ err_response.responseHeader.timestamp = UA_DateTime_now();
+ err_response.responseHeader.serviceResult = error;
+ UA_SecureChannel_sendSymmetricMessage(channel, requestId, UA_MESSAGETYPE_MSG,
+ &err_response, &UA_TYPES[UA_TYPES_PUBLISHRESPONSE]);
+}
+
+void
+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");
+
+ /* Return an error if the session has no subscription */
+ if(LIST_EMPTY(&session->serverSubscriptions)) {
+ subscriptionSendError(session->header.channel, request->requestHeader.requestHandle,
+ requestId, UA_STATUSCODE_BADNOSUBSCRIPTION);
+ return;
+ }
+
+ /* 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)) {
+ subscriptionSendError(session->header.channel, requestId,
+ request->requestHeader.requestHandle,
+ UA_STATUSCODE_BADINTERNALERROR);
+ return;
+ }
+ }
+
+ /* Allocate the response to store it in the retransmission queue */
+ UA_PublishResponseEntry *entry = (UA_PublishResponseEntry *)
+ UA_malloc(sizeof(UA_PublishResponseEntry));
+ if(!entry) {
+ subscriptionSendError(session->header.channel, requestId,
+ request->requestHeader.requestHandle,
+ UA_STATUSCODE_BADOUTOFMEMORY);
+ return;
+ }
+
+ /* Prepare the response */
+ entry->requestId = requestId;
+ UA_PublishResponse *response = &entry->response;
+ UA_PublishResponse_init(response);
+ response->responseHeader.requestHandle = request->requestHeader.requestHandle;
+
+ /* Allocate the results array to acknowledge the acknowledge */
+ if(request->subscriptionAcknowledgementsSize > 0) {
+ response->results = (UA_StatusCode *)
+ UA_Array_new(request->subscriptionAcknowledgementsSize,
+ &UA_TYPES[UA_TYPES_STATUSCODE]);
+ if(!response->results) {
+ UA_free(entry);
+ subscriptionSendError(session->header.channel, requestId,
+ request->requestHeader.requestHandle,
+ UA_STATUSCODE_BADOUTOFMEMORY);
+ return;
+ }
+ response->resultsSize = request->subscriptionAcknowledgementsSize;
+ }
+
+ /* Delete Acknowledged Subscription Messages */
+ for(size_t i = 0; i < request->subscriptionAcknowledgementsSize; ++i) {
+ UA_SubscriptionAcknowledgement *ack = &request->subscriptionAcknowledgements[i];
+ UA_Subscription *sub = UA_Session_getSubscriptionById(session, ack->subscriptionId);
+ if(!sub) {
+ response->results[i] = UA_STATUSCODE_BADSUBSCRIPTIONIDINVALID;
+ UA_LOG_DEBUG_SESSION(server->config.logger, session,
+ "Cannot process acknowledgements subscription %u",
+ ack->subscriptionId);
+ continue;
+ }
+ /* Remove the acked transmission from the retransmission queue */
+ response->results[i] = UA_Subscription_removeRetransmissionMessage(sub, ack->sequenceNumber);
+ }
+
+ /* Queue the publish response. It will be dequeued in a repeated publish
+ * callback. This can also be triggered right now for a late
+ * subscription. */
+ UA_Session_queuePublishReq(session, entry, false);
+ 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;
+ }
+ }
+ }
+
+ /* 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;
+
+ repeat:
+ while(immediate) {
+ if(immediate->state == UA_SUBSCRIPTIONSTATE_LATE) {
+ session->lastSeenSubscriptionId = immediate->subscriptionId;
+ UA_LOG_DEBUG_SESSION(server->config.logger, session,
+ "Subscription %u | Response on a late subscription",
+ immediate->subscriptionId);
+ UA_Subscription_publish(server, immediate);
+ return;
+ }
+ immediate = LIST_NEXT(immediate, listEntry);
+ }
+
+ /* Restart at the beginning of the list */
+ if(found) {
+ immediate = LIST_FIRST(&session->serverSubscriptions);
+ found = false;
+ goto repeat;
+ }
+
+ /* No late subscription this time */
+ session->lastSeenSubscriptionId = 0;
+}
+
+static void
+Operation_DeleteSubscription(UA_Server *server, UA_Session *session, void *_,
+ 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 %u | Subscription deleted",
+ *subscriptionId);
+ } else {
+ UA_LOG_DEBUG_SESSION(server->config.logger, session,
+ "Deleting Subscription with Id %u failed with error code %s",
+ *subscriptionId, UA_StatusCode_name(*result));
+ }
+}
+
+void
+Service_DeleteSubscriptions(UA_Server *server, UA_Session *session,
+ const UA_DeleteSubscriptionsRequest *request,
+ UA_DeleteSubscriptionsResponse *response) {
+ UA_LOG_DEBUG_SESSION(server->config.logger, session, "Processing DeleteSubscriptionsRequest");
+
+ 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);
+}
+
+static void
+Operation_DeleteMonitoredItem(UA_Server *server, UA_Session *session, UA_Subscription *sub,
+ UA_UInt32 *monitoredItemId, UA_StatusCode *result) {
+ *result = UA_Subscription_deleteMonitoredItem(server, sub, *monitoredItemId);
+}
+
+void
+Service_DeleteMonitoredItems(UA_Server *server, UA_Session *session,
+ const UA_DeleteMonitoredItemsRequest *request,
+ UA_DeleteMonitoredItemsResponse *response) {
+ UA_LOG_DEBUG_SESSION(server->config.logger, session, "Processing DeleteMonitoredItemsRequest");
+
+ if(server->config.maxMonitoredItemsPerCall != 0 &&
+ request->monitoredItemIdsSize > server->config.maxMonitoredItemsPerCall) {
+ response->responseHeader.serviceResult = UA_STATUSCODE_BADTOOMANYOPERATIONS;
+ return;
+ }
+
+ /* Get the subscription */
+ UA_Subscription *sub = UA_Session_getSubscriptionById(session, request->subscriptionId);
+ if(!sub) {
+ response->responseHeader.serviceResult = UA_STATUSCODE_BADSUBSCRIPTIONIDINVALID;
+ return;
+ }
+
+ /* Reset the subscription lifetime */
+ sub->currentLifetimeCount = 0;
+
+ 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]);
+}
+
+void
+Service_Republish(UA_Server *server, UA_Session *session, const UA_RepublishRequest *request,
+ UA_RepublishResponse *response) {
+ UA_LOG_DEBUG_SESSION(server->config.logger, session, "Processing RepublishRequest");
+
+ /* Get the subscription */
+ UA_Subscription *sub = UA_Session_getSubscriptionById(session, request->subscriptionId);
+ if(!sub) {
+ response->responseHeader.serviceResult = UA_STATUSCODE_BADSUBSCRIPTIONIDINVALID;
+ return;
+ }
+
+ /* Reset the subscription lifetime */
+ sub->currentLifetimeCount = 0;
+
+ /* Find the notification in the retransmission queue */
+ UA_NotificationMessageEntry *entry;
+ TAILQ_FOREACH(entry, &sub->retransmissionQueue, listEntry) {
+ if(entry->message.sequenceNumber == request->retransmitSequenceNumber)
+ break;
+ }
+ if(!entry) {
+ response->responseHeader.serviceResult = UA_STATUSCODE_BADMESSAGENOTAVAILABLE;
+ return;
+ }
+
+ response->responseHeader.serviceResult =
+ UA_NotificationMessage_copy(&entry->message, &response->notificationMessage);
+}
+
+#endif /* UA_ENABLE_SUBSCRIPTIONS */
+
+/*********************************** amalgamated original file "/home/jvoe/open62541/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
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * Copyright 2014-2017 (c) Julius Pfrommer, Fraunhofer IOSB
+ * Copyright 2014, 2017 (c) Florian Palm
+ * Copyright 2015 (c) Oleksiy Vasylyev
+ * Copyright 2017 (c) Stefan Profanter, fortiss GmbH
+ * Copyright 2017 (c) Mark Giraud, Fraunhofer IOSB
+ */
+
+
+void
+Service_OpenSecureChannel(UA_Server *server, UA_SecureChannel *channel,
+ const UA_OpenSecureChannelRequest *request,
+ UA_OpenSecureChannelResponse *response) {
+ if(request->requestType == UA_SECURITYTOKENREQUESTTYPE_RENEW) {
+ /* Renew the channel */
+ response->responseHeader.serviceResult =
+ UA_SecureChannelManager_renew(&server->secureChannelManager,
+ channel, request, response);
+
+ /* Logging */
+ if(response->responseHeader.serviceResult == UA_STATUSCODE_GOOD) {
+ UA_LOG_DEBUG_CHANNEL(server->config.logger, channel,
+ "SecureChannel renewed");
+ } else {
+ UA_LOG_DEBUG_CHANNEL(server->config.logger, channel,
+ "Renewing SecureChannel failed");
+ }
+ return;
+ }
+
+ /* Must be ISSUE or RENEW */
+ if(request->requestType != UA_SECURITYTOKENREQUESTTYPE_ISSUE) {
+ response->responseHeader.serviceResult = UA_STATUSCODE_BADINTERNALERROR;
+ return;
+ }
+
+ /* Open the channel */
+ response->responseHeader.serviceResult =
+ UA_SecureChannelManager_open(&server->secureChannelManager, channel,
+ request, response);
+
+ /* Logging */
+ if(response->responseHeader.serviceResult == UA_STATUSCODE_GOOD) {
+ UA_LOG_INFO_CHANNEL(server->config.logger, channel,
+ "Opened SecureChannel");
+ } else {
+ UA_LOG_INFO_CHANNEL(server->config.logger, channel,
+ "Opening a SecureChannel failed");
+ }
+}
+
+/* The server does not send a CloseSecureChannel response */
+void
+Service_CloseSecureChannel(UA_Server *server, UA_SecureChannel *channel) {
+ UA_LOG_INFO_CHANNEL(server->config.logger, channel, "CloseSecureChannel");
+ UA_SecureChannelManager_close(&server->secureChannelManager,
+ channel->securityToken.channelId);
+}
+
+/*********************************** amalgamated original file "/home/jvoe/open62541/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
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * Copyright 2014-2017 (c) Julius Pfrommer, Fraunhofer IOSB
+ * Copyright 2014-2017 (c) Florian Palm
+ * Copyright 2015-2016 (c) Sten Grüner
+ * Copyright 2015-2016 (c) Chris Iatrou
+ * Copyright 2015-2016 (c) Oleksiy Vasylyev
+ * Copyright 2017 (c) Julian Grothoff
+ * Copyright 2016 (c) LEvertz
+ * Copyright 2016 (c) Lorenz Haas
+ * Copyright 2017 (c) frax2222
+ * Copyright 2017-2018 (c) Stefan Profanter, fortiss GmbH
+ * Copyright 2017 (c) Christian von Arnim
+ * Copyright 2017 (c) Henrik Norrman
+ */
+
+
+/*********************/
+/* Edit Node Context */
+/*********************/
+
+UA_StatusCode
+UA_Server_getNodeContext(UA_Server *server, UA_NodeId nodeId,
+ void **nodeContext) {
+ const UA_Node *node = UA_Nodestore_get(server, &nodeId);
+ if(!node)
+ return UA_STATUSCODE_BADNODEIDUNKNOWN;
+
+ *nodeContext = node->context;
+ UA_Nodestore_release(server, node);
+ return UA_STATUSCODE_GOOD;
+}
+
+static UA_StatusCode
+editNodeContext(UA_Server *server, UA_Session* session,
+ UA_Node* node, void *context) {
+ node->context = context;
+ return UA_STATUSCODE_GOOD;
+}
+
+UA_StatusCode
+UA_Server_setNodeContext(UA_Server *server, UA_NodeId nodeId,
+ void *nodeContext) {
+ UA_StatusCode retval =
+ UA_Server_editNode(server, &server->adminSession, &nodeId,
+ (UA_EditNodeCallback)editNodeContext, nodeContext);
+ return retval;
+}
+
+/**********************/
+/* Consistency Checks */
+/**********************/
+
+
+#define UA_PARENT_REFERENCES_COUNT 2
+
+const UA_NodeId parentReferences[UA_PARENT_REFERENCES_COUNT] = {
+ {
+ 0, UA_NODEIDTYPE_NUMERIC, {UA_NS0ID_HASSUBTYPE}
+ },
+ {
+ 0, UA_NODEIDTYPE_NUMERIC, {UA_NS0ID_HASCOMPONENT}
+ }
+};
+
+
+/* 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,
+ const UA_NodeId *parentNodeId, const UA_NodeId *referenceTypeId) {
+ /* Objects do not need a parent (e.g. mandatory/optional modellingrules) */
+ if(nodeClass == UA_NODECLASS_OBJECT && UA_NodeId_isNull(parentNodeId) &&
+ UA_NodeId_isNull(referenceTypeId))
+ return UA_STATUSCODE_GOOD;
+
+ /* Omit checks during bootstrap */
+ if(server->bootstrapNS0)
+ return UA_STATUSCODE_GOOD;
+
+ /* See if the parent exists */
+ const UA_Node *parent = UA_Nodestore_get(server, parentNodeId);
+ if(!parent) {
+ UA_LOG_INFO_SESSION(server->config.logger, session,
+ "AddNodes: Parent node not found");
+ return UA_STATUSCODE_BADPARENTNODEIDINVALID;
+ }
+
+ UA_NodeClass parentNodeClass = parent->nodeClass;
+ UA_Nodestore_release(server, parent);
+
+ /* Check the referencetype exists */
+ const UA_ReferenceTypeNode *referenceType = (const UA_ReferenceTypeNode*)
+ UA_Nodestore_get(server, referenceTypeId);
+ if(!referenceType) {
+ UA_LOG_INFO_SESSION(server->config.logger, session,
+ "AddNodes: 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_INFO_SESSION(server->config.logger, session,
+ "AddNodes: Reference type to the parent invalid");
+ UA_Nodestore_release(server, (const UA_Node*)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 */
+ if(referenceTypeIsAbstract == true) {
+ UA_LOG_INFO_SESSION(server->config.logger, session,
+ "AddNodes: 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: New type node need to have a "
+ "HasSubType reference");
+ 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: New type node needs to be of the same "
+ "node type as the parent");
+ return UA_STATUSCODE_BADPARENTNODEIDINVALID;
+ }
+ return UA_STATUSCODE_GOOD;
+ }
+
+ /* Test if the referencetype is hierarchical */
+ const UA_NodeId hierarchicalReference =
+ UA_NODEID_NUMERIC(0, UA_NS0ID_HIERARCHICALREFERENCES);
+ if(!isNodeInTree(&server->config.nodestore, referenceTypeId,
+ &hierarchicalReference, &subtypeId, 1)) {
+ UA_LOG_INFO_SESSION(server->config.logger, session,
+ "AddNodes: Reference type is not hierarchical");
+ return UA_STATUSCODE_BADREFERENCETYPEIDINVALID;
+ }
+
+ return UA_STATUSCODE_GOOD;
+}
+
+static UA_StatusCode
+typeCheckVariableNode(UA_Server *server, UA_Session *session,
+ const UA_VariableNode *node,
+ const UA_VariableTypeNode *vt,
+ const UA_NodeId *parentNodeId) {
+ /* 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;
+
+ /* Check the datatype against the vt */
+ if(!compatibleDataType(server, &node->dataType, &vt->dataType, false))
+ return UA_STATUSCODE_BADTYPEMISMATCH;
+
+ /* Check valueRank against array dimensions */
+ if(!compatibleValueRankArrayDimensions(server, session, node->valueRank, node->arrayDimensionsSize))
+ return UA_STATUSCODE_BADTYPEMISMATCH;
+
+ /* If variable node is created below BaseObjectType and has its default valueRank of -2,
+ * skip the test */
+ const UA_NodeId objectTypes = UA_NODEID_NUMERIC(0, UA_NS0ID_BASEOBJECTTYPE);
+
+ // TODO handle subtypes of parent reference types
+ if(node->valueRank != vt->valueRank &&
+ node->valueRank != UA_VariableAttributes_default.valueRank &&
+ !isNodeInTree(&server->config.nodestore, parentNodeId, &objectTypes,
+ parentReferences, UA_PARENT_REFERENCES_COUNT)) {
+ /* Check valueRank against the vt */
+ if(!compatibleValueRanks(node->valueRank, vt->valueRank))
+ return UA_STATUSCODE_BADTYPEMISMATCH;
+ }
+
+ /* Check array dimensions against the vt */
+ if(!compatibleArrayDimensions(vt->arrayDimensionsSize, vt->arrayDimensions,
+ node->arrayDimensionsSize, node->arrayDimensions))
+ 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 = UA_Server_writeValue(server, node->nodeId, value.value);
+ UA_DataValue_deleteMembers(&value);
+ }
+ return retval;
+}
+
+/********************/
+/* Instantiate Node */
+/********************/
+
+static const UA_NodeId baseDataVariableType =
+ {0, UA_NODEIDTYPE_NUMERIC, {UA_NS0ID_BASEDATAVARIABLETYPE}};
+static const UA_NodeId baseObjectType =
+ {0, UA_NODEIDTYPE_NUMERIC, {UA_NS0ID_BASEOBJECTTYPE}};
+
+/* Use attributes from the variable type wherever required */
+static UA_StatusCode
+useVariableTypeAttributes(UA_Server *server, UA_Session *session,
+ UA_VariableNode *node, const UA_AddNodesItem *item) {
+ const UA_VariableAttributes *attributes = (const UA_VariableAttributes*)
+ item->nodeAttributes.content.decoded.data;
+
+ /* Select the type definition */
+ const UA_NodeId *typeDefinition;
+ if(node->nodeClass == UA_NODECLASS_VARIABLE)
+ typeDefinition = &item->typeDefinition.nodeId;
+ else /* UA_NODECLASS_VARIABLETYPE */
+ typeDefinition = &item->parentNodeId.nodeId;
+
+ /* Replace an empty typeDefinition with the most permissive default */
+ if(UA_NodeId_isNull(typeDefinition))
+ typeDefinition = &baseDataVariableType;
+
+ const UA_VariableTypeNode *vt = (const UA_VariableTypeNode*)
+ UA_Nodestore_get(server, typeDefinition);
+ if(!vt || vt->nodeClass != UA_NODECLASS_VARIABLETYPE) {
+ UA_Nodestore_release(server, (const UA_Node*)vt);
+ return UA_STATUSCODE_BADTYPEMISMATCH;
+ }
+
+ /* 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_StatusCode retval = UA_STATUSCODE_GOOD;
+ if(!attributes->value.type) {
+ UA_LOG_DEBUG_SESSION(server->config.logger, session,
+ "AddNodes: No value given; Copy the value"
+ "from the TypeDefinition");
+ UA_DataValue vt_value;
+ UA_DataValue_init(&vt_value);
+ retval = readValueAttribute(server, session,
+ (const UA_VariableNode*)vt, &vt_value);
+ if(retval == UA_STATUSCODE_GOOD && vt_value.hasValue) {
+ retval = UA_Variant_copy(&vt_value.value, &node->value.data.value.value);
+ node->value.data.value.hasValue = true;
+ }
+ UA_DataValue_deleteMembers(&vt_value);
+ }
+
+ /* If no datatype is given, use the datatype of the vt */
+ if(retval == UA_STATUSCODE_GOOD && UA_NodeId_isNull(&node->dataType)) {
+ UA_LOG_INFO_SESSION(server->config.logger, session, "AddNodes: "
+ "No datatype given; Copy the datatype attribute "
+ "from the TypeDefinition");
+ retval = UA_NodeId_copy(&vt->dataType, &node->dataType);
+ }
+
+ /* TODO: If the vt has arraydimensions but this variable does not, copy */
+
+ UA_Nodestore_release(server, (const UA_Node*)vt);
+ return retval;
+}
+
+/* Search for an instance of "browseName" in node searchInstance. Used during
+ * copyChildNodes to find overwritable/mergable nodes. Does not touch
+ * outInstanceNodeId if no child is found. */
+static UA_StatusCode
+findChildByBrowsename(UA_Server *server, UA_Session *session,
+ const UA_NodeId *searchInstance,
+ const UA_QualifiedName *browseName,
+ UA_NodeId *outInstanceNodeId) {
+ UA_BrowseDescription bd;
+ UA_BrowseDescription_init(&bd);
+ bd.nodeId = *searchInstance;
+ bd.referenceTypeId = UA_NODEID_NUMERIC(0, UA_NS0ID_AGGREGATES);
+ bd.includeSubtypes = true;
+ bd.browseDirection = UA_BROWSEDIRECTION_FORWARD;
+ bd.nodeClassMask = UA_NODECLASS_OBJECT | UA_NODECLASS_VARIABLE | UA_NODECLASS_METHOD;
+ bd.resultMask = UA_BROWSERESULTMASK_NODECLASS | UA_BROWSERESULTMASK_BROWSENAME;
+
+ 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 br.statusCode;
+
+ UA_StatusCode retval = UA_STATUSCODE_GOOD;
+ for(size_t i = 0; i < br.referencesSize; ++i) {
+ UA_ReferenceDescription *rd = &br.references[i];
+ if(rd->browseName.namespaceIndex == browseName->namespaceIndex &&
+ UA_String_equal(&rd->browseName.name, &browseName->name)) {
+ retval = UA_NodeId_copy(&rd->nodeId.nodeId, outInstanceNodeId);
+ break;
+ }
+ }
+
+ UA_BrowseResult_deleteMembers(&br);
+ return retval;
+}
+
+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,
+ const UA_NodeId *childNodeId) {
+ /* Get the child */
+ const UA_Node *child = UA_Nodestore_get(server, childNodeId);
+ if(!child)
+ 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))
+ continue;
+ if(refs->isInverse)
+ continue;
+ for(size_t j = 0; j < refs->targetIdsSize; ++j) {
+ if(UA_NodeId_equal(&mandatoryId, &refs->targetIds[j].nodeId)) {
+ UA_Nodestore_release(server, child);
+ return true;
+ }
+ }
+ }
+
+ UA_Nodestore_release(server, child);
+ return false;
+}
+
+static UA_StatusCode
+copyChildNodes(UA_Server *server, UA_Session *session,
+ const UA_NodeId *sourceNodeId,
+ const UA_NodeId *destinationNodeId);
+
+static void
+Operation_addReference(UA_Server *server, UA_Session *session, void *context,
+ const UA_AddReferencesItem *item, UA_StatusCode *retval);
+
+
+/*
+ * This method only 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'
+ */
+static void deleteReferencesSubset(UA_Node *node, size_t referencesSkipSize, UA_NodeId* referencesSkip) {
+ if(referencesSkipSize == 0) {
+ UA_Node_deleteReferences(node);
+ return;
+ }
+
+ /* Let's count if there are references left. If not just delete all the references.
+ * It's faster */
+ size_t newSize = 0;
+ for(size_t i = 0; i < node->referencesSize; ++i) {
+ for(size_t j = 0; j < referencesSkipSize; j++) {
+ if(UA_NodeId_equal(&node->references[i].referenceTypeId, &referencesSkip[j])) {
+ newSize++;
+ }
+ }
+ }
+ if(newSize == 0) {
+ UA_Node_deleteReferences(node);
+ return;
+ }
+
+ /* Now copy the remaining references to a new array */
+ UA_NodeReferenceKind *newReferences = (UA_NodeReferenceKind *)UA_malloc(sizeof(UA_NodeReferenceKind) * (newSize));
+ size_t curr = 0;
+ UA_StatusCode retval = UA_STATUSCODE_GOOD;
+ for(size_t i = 0; i < node->referencesSize && retval == UA_STATUSCODE_GOOD; ++i) {
+ for(size_t j = 0; j < referencesSkipSize; j++) {
+ if(!UA_NodeId_equal(&node->references[i].referenceTypeId, &referencesSkip[j]))
+ continue;
+
+ // copy the reference
+ UA_NodeReferenceKind *srefs = &node->references[i];
+ UA_NodeReferenceKind *drefs = &newReferences[curr++];
+ drefs->isInverse = srefs->isInverse;
+ retval = UA_NodeId_copy(&srefs->referenceTypeId, &drefs->referenceTypeId);
+ if(retval != UA_STATUSCODE_GOOD)
+ break;
+ retval = UA_Array_copy(srefs->targetIds, srefs->targetIdsSize,
+ (void**)&drefs->targetIds,
+ &UA_TYPES[UA_TYPES_EXPANDEDNODEID]);
+ if(retval != UA_STATUSCODE_GOOD)
+ break;
+ drefs->targetIdsSize = srefs->targetIdsSize;
+ break;
+ }
+ if(retval != UA_STATUSCODE_GOOD) {
+ for(size_t k=0; k<i; k++) {
+ UA_NodeReferenceKind *refs = &newReferences[i];
+ for(size_t j = 0; j < refs->targetIdsSize; ++j)
+ UA_ExpandedNodeId_deleteMembers(&refs->targetIds[j]);
+ UA_Array_delete(refs->targetIds, refs->targetIdsSize, &UA_TYPES[UA_TYPES_EXPANDEDNODEID]);
+ UA_NodeId_deleteMembers(&refs->referenceTypeId);
+ }
+ }
+ }
+
+ UA_Node_deleteReferences(node);
+ if(retval == UA_STATUSCODE_GOOD) {
+ node->references = newReferences;
+ node->referencesSize = newSize;
+ } else {
+ UA_free(newReferences);
+ }
+}
+
+static UA_StatusCode
+AddNode_typeCheckAddRefs(UA_Server *server, UA_Session *session, const UA_NodeId *nodeId,
+ const UA_NodeId *parentNodeId, const UA_NodeId *referenceTypeId,
+ const UA_NodeId *typeDefinitionId);
+
+static UA_StatusCode
+copyChildNode(UA_Server *server, UA_Session *session,
+ const UA_NodeId *destinationNodeId,
+ const UA_ReferenceDescription *rd) {
+ UA_NodeId existingChild = UA_NODEID_NULL;
+ UA_StatusCode retval =
+ findChildByBrowsename(server, session, destinationNodeId,
+ &rd->browseName, &existingChild);
+ if(retval != UA_STATUSCODE_GOOD)
+ return retval;
+
+ /* Have a child with that browseName. Try to deep-copy missing members. */
+ if(!UA_NodeId_isNull(&existingChild)) {
+ if(rd->nodeClass == UA_NODECLASS_VARIABLE ||
+ rd->nodeClass == UA_NODECLASS_OBJECT)
+ retval = copyChildNodes(server, session, &rd->nodeId.nodeId, &existingChild);
+ UA_NodeId_deleteMembers(&existingChild);
+ return retval;
+ }
+
+ /* Is the child mandatory? If not, skip */
+ if(!isMandatoryChild(server, session, &rd->nodeId.nodeId))
+ return UA_STATUSCODE_GOOD;
+
+ /* No existing child with that browsename. Create it. */
+ if(rd->nodeClass == UA_NODECLASS_METHOD) {
+ /* Add a reference to the method in the objecttype */
+ UA_AddReferencesItem newItem;
+ UA_AddReferencesItem_init(&newItem);
+ newItem.sourceNodeId = *destinationNodeId;
+ newItem.referenceTypeId = rd->referenceTypeId;
+ newItem.isForward = true;
+ newItem.targetNodeId = rd->nodeId;
+ newItem.targetNodeClass = UA_NODECLASS_METHOD;
+ Operation_addReference(server, session, NULL, &newItem, &retval);
+ return retval;
+ }
+
+ /* Node exists and is a variable or object. Instantiate missing mandatory
+ * children */
+ if(rd->nodeClass == UA_NODECLASS_VARIABLE ||
+ rd->nodeClass == UA_NODECLASS_OBJECT) {
+ /* Get the node */
+ UA_Node *node;
+ retval = UA_Nodestore_getCopy(server, &rd->nodeId.nodeId, &node);
+ if(retval != UA_STATUSCODE_GOOD)
+ return retval;
+
+ /* Get the type */
+ const UA_Node *type = getNodeType(server, node);
+ const UA_NodeId *typeId;
+ if(type)
+ typeId = &type->nodeId;
+ else
+ typeId = &UA_NODEID_NULL;
+
+ /* Reset the NodeId (random numeric id will be assigned in the nodestore) */
+ UA_NodeId_deleteMembers(&node->nodeId);
+ node->nodeId.namespaceIndex = destinationNodeId->namespaceIndex;
+
+ /* 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);
+ deleteReferencesSubset(node, 1, &modellingRuleReferenceId);
+
+ /* Add the node to the nodestore */
+ UA_NodeId newNodeId;
+ retval = UA_Nodestore_insert(server, node, &newNodeId);
+ if(retval != UA_STATUSCODE_GOOD) {
+ UA_Nodestore_release(server, type);
+ return retval;
+ }
+
+ /* Add all the children of this child to the new child node to make sure we take
+ * the values from the nearest inherited object first.
+ * The call to addNode_finish will then only add the children from the type and
+ * thus skip the direct children of rd->nodeId.nodeId */
+ copyChildNodes(server, session, &rd->nodeId.nodeId, &newNodeId);
+
+ /* Add the parent reference */
+ retval = AddNode_typeCheckAddRefs(server, session, &newNodeId, destinationNodeId,
+ &rd->referenceTypeId, typeId);
+ if(retval != UA_STATUSCODE_GOOD) {
+ UA_Nodestore_delete(server, node);
+ UA_Nodestore_release(server, type);
+ return retval;
+ }
+
+ /* Call addnode_finish, this recursively adds additional members, the type
+ * definition and so on of the base type of this child, if they are not yet
+ * in the destination */
+ retval |= Operation_addNode_finish(server, session, &newNodeId);
+ UA_NodeId_deleteMembers(&newNodeId);
+ UA_Nodestore_release(server, type);
+ }
+ return retval;
+}
+
+/* Copy any children of Node sourceNodeId to another node destinationNodeId. */
+static UA_StatusCode
+copyChildNodes(UA_Server *server, UA_Session *session,
+ const UA_NodeId *sourceNodeId, const UA_NodeId *destinationNodeId) {
+ /* Browse to get all children of the source */
+ UA_BrowseDescription bd;
+ UA_BrowseDescription_init(&bd);
+ bd.nodeId = *sourceNodeId;
+ bd.referenceTypeId = UA_NODEID_NUMERIC(0, UA_NS0ID_AGGREGATES);
+ bd.includeSubtypes = true;
+ bd.browseDirection = UA_BROWSEDIRECTION_FORWARD;
+ bd.nodeClassMask = UA_NODECLASS_OBJECT | UA_NODECLASS_VARIABLE | UA_NODECLASS_METHOD;
+ bd.resultMask = UA_BROWSERESULTMASK_REFERENCETYPEID | UA_BROWSERESULTMASK_NODECLASS |
+ UA_BROWSERESULTMASK_BROWSENAME;
+
+ 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 br.statusCode;
+
+ UA_StatusCode retval = UA_STATUSCODE_GOOD;
+ for(size_t i = 0; i < br.referencesSize; ++i) {
+ UA_ReferenceDescription *rd = &br.references[i];
+ retval |= copyChildNode(server, session, destinationNodeId, rd);
+ }
+
+ UA_BrowseResult_deleteMembers(&br);
+ return retval;
+}
+
+static UA_StatusCode
+addChildren(UA_Server *server, UA_Session *session,
+ const UA_Node *node, const UA_Node *type) {
+ /* Get the hierarchy of the type and all its supertypes */
+ UA_NodeId *hierarchy = NULL;
+ size_t hierarchySize = 0;
+ UA_StatusCode retval = getTypeHierarchy(&server->config.nodestore, &type->nodeId,
+ &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 |= copyChildNodes(server, session, &hierarchy[i], &node->nodeId);
+ UA_Array_delete(hierarchy, hierarchySize, &UA_TYPES[UA_TYPES_NODEID]);
+ return retval;
+}
+
+/* Calls the global destructor internally of the global constructor succeeds and
+ * the type-level constructor fails. */
+static UA_StatusCode callConstructors(UA_Server *server, UA_Session *session,
+ const UA_Node *node, const UA_Node *type) {
+ /* Get the node type constructor */
+ const UA_NodeTypeLifecycle *lifecycle = NULL;
+ if(node->nodeClass == UA_NODECLASS_OBJECT) {
+ const UA_ObjectTypeNode *ot = (const UA_ObjectTypeNode*)type;
+ lifecycle = &ot->lifecycle;
+ } else if(node->nodeClass == UA_NODECLASS_VARIABLE) {
+ const UA_VariableTypeNode *vt = (const UA_VariableTypeNode*)type;
+ lifecycle = &vt->lifecycle;
+ }
+
+ /* Call the global constructor */
+ void *context = node->context;
+ UA_StatusCode retval = UA_STATUSCODE_GOOD;
+ if(server->config.nodeLifecycle.constructor)
+ retval = server->config.nodeLifecycle.constructor(server, &session->sessionId,
+ session->sessionHandle,
+ &node->nodeId, &context);
+
+ /* Call the type constructor */
+ if(retval == UA_STATUSCODE_GOOD && lifecycle && lifecycle->constructor)
+ retval = lifecycle->constructor(server, &session->sessionId,
+ session->sessionHandle, &type->nodeId,
+ type->context, &node->nodeId, &context);
+
+ /* 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)editNodeContext,
+ context);
+
+ /* Fail. Call the global destructor. */
+ if(retval != UA_STATUSCODE_GOOD && server->config.nodeLifecycle.destructor)
+ server->config.nodeLifecycle.destructor(server, &session->sessionId,
+ session->sessionHandle,
+ &node->nodeId, context);
+
+ return retval;
+}
+
+static UA_StatusCode
+addTypeDefRef(UA_Server *server, UA_Session *session,
+ const UA_Node *node, const UA_Node *type) {
+ UA_StatusCode retval = UA_STATUSCODE_GOOD;
+ UA_AddReferencesItem addref;
+ UA_AddReferencesItem_init(&addref);
+ addref.sourceNodeId = node->nodeId;
+ addref.referenceTypeId = UA_NODEID_NUMERIC(0, UA_NS0ID_HASTYPEDEFINITION);
+ addref.isForward = true;
+ addref.targetNodeId.nodeId = type->nodeId;
+ Operation_addReference(server, session, NULL, &addref, &retval);
+ return retval;
+}
+
+static UA_StatusCode
+getTypeDef(UA_Server *server, const UA_Node *node, UA_NodeId **typeDefinitionId) {
+ UA_NodeId hasTypeDef = UA_NODEID_NUMERIC(0, UA_NS0ID_HASTYPEDEFINITION);
+ for (size_t i=0; i< node->referencesSize; i++) {
+ if (node->references[i].isInverse == UA_FALSE && UA_NodeId_equal(&node->references[i].referenceTypeId, &hasTypeDef) &&
+ node->references[i].targetIdsSize > 0) {
+ *typeDefinitionId = &node->references[i].targetIds[0].nodeId;
+ return UA_STATUSCODE_GOOD;
+ }
+ }
+
+ return UA_STATUSCODE_BADNOTFOUND;
+}
+
+static UA_StatusCode
+addParentRef(UA_Server *server, UA_Session *session,
+ const UA_NodeId *nodeId,
+ const UA_NodeId *referenceTypeId,
+ const UA_NodeId *parentNodeId) {
+ UA_StatusCode retval = UA_STATUSCODE_GOOD;
+ UA_AddReferencesItem ref_item;
+ UA_AddReferencesItem_init(&ref_item);
+ ref_item.sourceNodeId = *nodeId;
+ ref_item.referenceTypeId = *referenceTypeId;
+ ref_item.isForward = false;
+ ref_item.targetNodeId.nodeId = *parentNodeId;
+ Operation_addReference(server, session, NULL, &ref_item, &retval);
+ return retval;
+}
+
+/************/
+/* Add Node */
+/************/
+
+static void
+removeDeconstructedNode(UA_Server *server, UA_Session *session,
+ const UA_Node *node, UA_Boolean removeTargetRefs);
+
+static const UA_NodeId hasSubtype = {0, UA_NODEIDTYPE_NUMERIC, {UA_NS0ID_HASSUBTYPE}};
+
+static UA_StatusCode
+AddNode_typeCheckAddRefs(UA_Server *server, UA_Session *session, const UA_NodeId *nodeId,
+ const UA_NodeId *parentNodeId, const UA_NodeId *referenceTypeId,
+ const UA_NodeId *typeDefinitionId) {
+ /* Get the node */
+ const UA_Node *node = UA_Nodestore_get(server, nodeId);
+ if(!node)
+ return UA_STATUSCODE_BADNODEIDUNKNOWN;
+
+ UA_StatusCode retval = UA_STATUSCODE_GOOD;
+ const UA_Node *type = NULL;
+
+ /* 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) {
+ 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)
+ typeDefinitionId = parentNodeId;
+ UA_Nodestore_release(server, parentNode);
+ }
+ }
+
+ if(server->bootstrapNS0)
+ goto get_type;
+
+ /* Check parent reference. Objects may have no parent. */
+ retval = checkParentReference(server, session, node->nodeClass,
+ parentNodeId, referenceTypeId);
+ if(retval != UA_STATUSCODE_GOOD) {
+ UA_LOG_INFO_SESSION(server->config.logger, session,
+ "AddNodes: The parent reference is invalid");
+ goto cleanup;
+ }
+
+ /* Replace empty typeDefinition with the most permissive default */
+ if((node->nodeClass == UA_NODECLASS_VARIABLE ||
+ node->nodeClass == UA_NODECLASS_OBJECT) &&
+ UA_NodeId_isNull(typeDefinitionId)) {
+ UA_LOG_INFO_SESSION(server->config.logger, session,
+ "AddNodes: No TypeDefinition; Use the default "
+ "TypeDefinition for the Variable/Object");
+ if(node->nodeClass == UA_NODECLASS_VARIABLE)
+ typeDefinitionId = &baseDataVariableType;
+ else
+ typeDefinitionId = &baseObjectType;
+ }
+
+ get_type:
+ /* Get the node type. There must be a typedefinition for variables, objects
+ * and type-nodes. See the above checks. */
+ if(!UA_NodeId_isNull(typeDefinitionId)) {
+ /* Get the type node */
+ type = UA_Nodestore_get(server, typeDefinitionId);
+ if(!type) {
+ UA_LOG_INFO_SESSION(server->config.logger, session,
+ "AddNodes: Node type not found in nodestore");
+ retval = UA_STATUSCODE_BADTYPEDEFINITIONINVALID;
+ goto cleanup;
+ }
+
+ UA_Boolean typeOk = UA_FALSE;
+ switch(node->nodeClass) {
+ case UA_NODECLASS_DATATYPE:
+ typeOk = type->nodeClass == UA_NODECLASS_DATATYPE;
+ break;
+ case UA_NODECLASS_METHOD:
+ typeOk = type->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;
+ break;
+ case UA_NODECLASS_REFERENCETYPE:
+ typeOk = type->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;
+ break;
+ case UA_NODECLASS_VIEW:
+ typeOk = type->nodeClass == UA_NODECLASS_VIEW;
+ break;
+ default:
+ typeOk = UA_FALSE;
+ }
+ if(!typeOk) {
+ UA_LOG_INFO_SESSION(server->config.logger, session,
+ "AddNodes: Type does not match node class");
+ 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(!server->bootstrapNS0 && node->nodeClass == UA_NODECLASS_VARIABLE) {
+ if(((const UA_VariableTypeNode*)type)->isAbstract) {
+ /* Abstract variable is allowed if parent is a children of a base data variable */
+ const UA_NodeId variableTypes = UA_NODEID_NUMERIC(0, UA_NS0ID_BASEDATAVARIABLETYPE);
+ /* A variable may be of an object type which again is below BaseObjectType */
+ const UA_NodeId objectTypes = UA_NODEID_NUMERIC(0, UA_NS0ID_BASEOBJECTTYPE);
+ // TODO handle subtypes of parent reference types
+ if(!isNodeInTree(&server->config.nodestore, parentNodeId, &variableTypes,
+ parentReferences, UA_PARENT_REFERENCES_COUNT) &&
+ !isNodeInTree(&server->config.nodestore, parentNodeId, &objectTypes,
+ parentReferences, UA_PARENT_REFERENCES_COUNT)) {
+ UA_LOG_INFO_SESSION(server->config.logger, session,
+ "AddNodes: Type of variable node must "
+ "be VariableType and not cannot be abstract");
+ retval = UA_STATUSCODE_BADTYPEDEFINITIONINVALID;
+ goto cleanup;
+ }
+ }
+ }
+
+ if(!server->bootstrapNS0 && node->nodeClass == UA_NODECLASS_OBJECT) {
+ if(((const UA_ObjectTypeNode*)type)->isAbstract) {
+ /* Object node created of an abstract ObjectType. Only allowed
+ * if within BaseObjectType folder */
+ const UA_NodeId objectTypes = UA_NODEID_NUMERIC(0, UA_NS0ID_BASEOBJECTTYPE);
+ // TODO handle subtypes of parent reference types
+ if(!isNodeInTree(&server->config.nodestore, parentNodeId, &objectTypes,
+ parentReferences, UA_PARENT_REFERENCES_COUNT)) {
+ UA_LOG_INFO_SESSION(server->config.logger, session,
+ "AddNodes: Type of object node must "
+ "be ObjectType and not be abstract");
+ retval = UA_STATUSCODE_BADTYPEDEFINITIONINVALID;
+ goto cleanup;
+ }
+ }
+ }
+ }
+
+ /* 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. */
+ if(type && (node->nodeClass == UA_NODECLASS_VARIABLE ||
+ node->nodeClass == UA_NODECLASS_VARIABLETYPE)) {
+ retval = typeCheckVariableNode(server, session, (const UA_VariableNode*)node,
+ (const UA_VariableTypeNode*)type, parentNodeId);
+ if(retval != UA_STATUSCODE_GOOD) {
+ UA_LOG_INFO_SESSION(server->config.logger, session,
+ "AddNodes: Type-checking the variable node "
+ "failed with error code %s", UA_StatusCode_name(retval));
+ goto cleanup;
+ }
+ }
+
+ /* Add reference to the parent */
+ if(!UA_NodeId_isNull(parentNodeId)) {
+ if(UA_NodeId_isNull(referenceTypeId)) {
+ UA_LOG_INFO_SESSION(server->config.logger, session,
+ "AddNodes: Reference to parent cannot be null");
+ retval = UA_STATUSCODE_BADTYPEDEFINITIONINVALID;
+ goto cleanup;
+ }
+
+ retval = addParentRef(server, session, &node->nodeId, referenceTypeId, parentNodeId);
+ if(retval != UA_STATUSCODE_GOOD) {
+ UA_LOG_INFO_SESSION(server->config.logger, session,
+ "AddNodes: Adding reference to parent failed");
+ goto cleanup;
+ }
+ }
+
+ /* Add a hasTypeDefinition reference */
+ if(node->nodeClass == UA_NODECLASS_VARIABLE ||
+ node->nodeClass == UA_NODECLASS_OBJECT) {
+ UA_assert(type != NULL); /* see above */
+ retval = addTypeDefRef(server, session, node, type);
+ if(retval != UA_STATUSCODE_GOOD)
+ UA_LOG_INFO_SESSION(server->config.logger, session,
+ "AddNodes: Adding a reference to the type "
+ "definition failed with error code %s",
+ UA_StatusCode_name(retval));
+ }
+
+ cleanup:
+ UA_Nodestore_release(server, node);
+ if(type)
+ UA_Nodestore_release(server, type);
+ if(retval != UA_STATUSCODE_GOOD)
+ UA_Server_deleteNode(server, *nodeId, UA_TRUE);
+ return retval;
+}
+
+/* Create the node and add it to the nodestore. But don't typecheck and add
+ * references so far */
+static UA_StatusCode
+AddNode_raw(UA_Server *server, UA_Session *session, void *nodeContext,
+ const UA_AddNodesItem *item, UA_NodeId *outNewNodeId) {
+ UA_assert(outNewNodeId);
+
+ /* Do not check access for server */
+ if(session != &server->adminSession && server->config.accessControl.allowAddNode &&
+ !server->config.accessControl.allowAddNode(server, &server->config.accessControl,
+ &session->sessionId, session->sessionHandle, item)) {
+ return UA_STATUSCODE_BADUSERACCESSDENIED;
+ }
+
+ /* Check the namespaceindex */
+ if(item->requestedNewNodeId.nodeId.namespaceIndex >= server->namespacesSize) {
+ UA_LOG_INFO_SESSION(server->config.logger, session,
+ "AddNodes: 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");
+ return UA_STATUSCODE_BADINTERNALERROR;
+ }
+
+ /* Create a node */
+ 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 "
+ "in the nodestore");
+ return UA_STATUSCODE_BADOUTOFMEMORY;
+ }
+
+ /* Fill the node attributes */
+ node->context = nodeContext;
+ UA_StatusCode retval = UA_STATUSCODE_GOOD;
+ retval |= UA_NodeId_copy(&item->requestedNewNodeId.nodeId, &node->nodeId);
+ retval |= UA_QualifiedName_copy(&item->browseName, &node->browseName);
+ retval |= UA_Node_setAttributes(node, item->nodeAttributes.content.decoded.data,
+ item->nodeAttributes.content.decoded.type);
+ if(retval != UA_STATUSCODE_GOOD) {
+ UA_LOG_INFO_SESSION(server->config.logger, session,
+ "AddNodes: Node could not create a node "
+ "with error code %s", UA_StatusCode_name(retval));
+ UA_Nodestore_delete(server, node);
+ return retval;
+ }
+
+ /* Use attributes from the typedefinition */
+ if(!server->bootstrapNS0 &&
+ (node->nodeClass == UA_NODECLASS_VARIABLE ||
+ node->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,
+ (UA_VariableNode*)node, item);
+ if(retval != UA_STATUSCODE_GOOD) {
+ UA_LOG_INFO_SESSION(server->config.logger, session,
+ "AddNodes: Using attributes from the variable type "
+ "failed with error code %s", UA_StatusCode_name(retval));
+ UA_Nodestore_delete(server, node);
+ return retval;
+ }
+ }
+
+ /* Add the node to the nodestore */
+ retval = UA_Nodestore_insert(server, node, outNewNodeId);
+ if(retval != UA_STATUSCODE_GOOD)
+ UA_LOG_INFO_SESSION(server->config.logger, session,
+ "AddNodes: Node could not add the new node "
+ "to the nodestore with error code %s",
+ UA_StatusCode_name(retval));
+ return retval;
+}
+
+/* Prepare the node, then add it to the nodestore */
+UA_StatusCode
+Operation_addNode_begin(UA_Server *server, UA_Session *session, void *nodeContext,
+ const UA_AddNodesItem *item, const UA_NodeId *parentNodeId,
+ const UA_NodeId *referenceTypeId, UA_NodeId *outNewNodeId) {
+ /* Create a temporary NodeId if none is returned */
+ UA_NodeId newId;
+ if(!outNewNodeId) {
+ UA_NodeId_init(&newId);
+ outNewNodeId = &newId;
+ }
+
+ /* Create the node and add it to the nodestore */
+ UA_StatusCode retval = AddNode_raw(server, session, nodeContext, item, outNewNodeId);
+ if(retval != UA_STATUSCODE_GOOD)
+ return retval;
+
+ /* Typecheck and add references to parent and type definition */
+ retval = AddNode_typeCheckAddRefs(server, session, outNewNodeId, parentNodeId,
+ referenceTypeId, &item->typeDefinition.nodeId);
+ if(outNewNodeId == &newId)
+ UA_NodeId_deleteMembers(&newId);
+ return retval;
+}
+
+/* Children, references, type-checking, constructors. */
+UA_StatusCode
+Operation_addNode_finish(UA_Server *server, UA_Session *session, const UA_NodeId *nodeId) {
+ UA_StatusCode retval = UA_STATUSCODE_GOOD;
+
+ /* Get the node */
+ const UA_Node *node = UA_Nodestore_get(server, nodeId);
+ if(!node)
+ return UA_STATUSCODE_BADNODEIDUNKNOWN;
+
+ const UA_Node *type = NULL;
+
+ /* Instantiate variables and objects */
+ if(node->nodeClass == UA_NODECLASS_VARIABLE ||
+ node->nodeClass == UA_NODECLASS_OBJECT) {
+ UA_NodeId *typeDefId;
+ retval = getTypeDef(server, node, &typeDefId);
+ if (retval != UA_STATUSCODE_GOOD) {
+ UA_LOG_INFO_SESSION(server->config.logger, session,
+ "AddNodes: Can not get type definition of node since it "
+ "has no 'hasTypeDef' reference");
+ goto cleanup;
+ }
+
+ /* Get the type node */
+ type = UA_Nodestore_get(server, typeDefId);
+ if(!type) {
+ UA_LOG_INFO_SESSION(server->config.logger, session,
+ "AddNodes: Node type not found in nodestore");
+ retval = UA_STATUSCODE_BADTYPEDEFINITIONINVALID;
+ goto cleanup;
+ }
+
+ /* Add (mandatory) child nodes from the type definition */
+ if(!server->bootstrapNS0) {
+ retval = addChildren(server, session, node, type);
+ if(retval != UA_STATUSCODE_GOOD) {
+ UA_LOG_INFO_SESSION(server->config.logger, session,
+ "AddNodes: Adding child nodes failed with error code %s",
+ UA_StatusCode_name(retval));
+ goto cleanup;
+ }
+ }
+ }
+
+ /* Call the constructor(s) */
+ retval = callConstructors(server, session, node, type);
+ if(retval != UA_STATUSCODE_GOOD) {
+ UA_LOG_INFO_SESSION(server->config.logger, session,
+ "AddNodes: Calling the node constructor(s) failed "
+ "with status code %s", UA_StatusCode_name(retval));
+ }
+
+ cleanup:
+ if(type)
+ UA_Nodestore_release(server, type);
+ if(retval != UA_STATUSCODE_GOOD)
+ removeDeconstructedNode(server, session, node, true);
+ UA_Nodestore_release(server, node);
+ return retval;
+}
+
+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,
+ &item->referenceTypeId, &result->addedNodeId);
+ if(result->statusCode != UA_STATUSCODE_GOOD)
+ return;
+
+ /* AddNodes_finish */
+ result->statusCode =
+ Operation_addNode_finish(server, session, &result->addedNodeId);
+
+ /* If finishing failed, the node was deleted */
+ if(result->statusCode != UA_STATUSCODE_GOOD)
+ UA_NodeId_deleteMembers(&result->addedNodeId);
+}
+
+void
+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");
+
+ if(server->config.maxNodesPerNodeManagement != 0 &&
+ request->nodesToAddSize > server->config.maxNodesPerNodeManagement) {
+ response->responseHeader.serviceResult = UA_STATUSCODE_BADTOOMANYOPERATIONS;
+ return;
+ }
+
+ 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]);
+}
+
+UA_StatusCode
+__UA_Server_addNode(UA_Server *server, const UA_NodeClass nodeClass,
+ const UA_NodeId *requestedNewNodeId,
+ const UA_NodeId *parentNodeId,
+ const UA_NodeId *referenceTypeId,
+ const UA_QualifiedName browseName,
+ const UA_NodeId *typeDefinition,
+ const UA_NodeAttributes *attr,
+ const UA_DataType *attributeType,
+ void *nodeContext, UA_NodeId *outNewNodeId) {
+ /* Create the AddNodesItem */
+ UA_AddNodesItem item;
+ UA_AddNodesItem_init(&item);
+ item.nodeClass = nodeClass;
+ item.requestedNewNodeId.nodeId = *requestedNewNodeId;
+ item.browseName = browseName;
+ 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;
+
+ /* Call the normal addnodes service */
+ UA_AddNodesResult result;
+ UA_AddNodesResult_init(&result);
+ Operation_addNode(server, &server->adminSession, nodeContext, &item, &result);
+ if(outNewNodeId)
+ *outNewNodeId = result.addedNodeId;
+ else
+ UA_NodeId_deleteMembers(&result.addedNodeId);
+ return result.statusCode;
+}
+
+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) {
+ 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;
+ return Operation_addNode_begin(server, &server->adminSession, nodeContext, &item,
+ &parentNodeId, &referenceTypeId, outNewNodeId);
+}
+
+UA_StatusCode
+UA_Server_addNode_finish(UA_Server *server, const UA_NodeId nodeId) {
+ return Operation_addNode_finish(server, &server->adminSession, &nodeId);
+}
+
+/****************/
+/* Delete Nodes */
+/****************/
+
+static void
+Operation_deleteReference(UA_Server *server, UA_Session *session, void *context,
+ const UA_DeleteReferencesItem *item, UA_StatusCode *retval);
+
+/* Remove references to this node (in the other nodes) */
+static void
+removeIncomingReferences(UA_Server *server, UA_Session *session,
+ const UA_Node *node) {
+ UA_DeleteReferencesItem item;
+ UA_DeleteReferencesItem_init(&item);
+ item.targetNodeId.nodeId = node->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->targetIdsSize; ++j) {
+ item.sourceNodeId = refs->targetIds[j].nodeId;
+ Operation_deleteReference(server, session, NULL, &item, &dummy);
+ }
+ }
+}
+
+static void
+deconstructNode(UA_Server *server, UA_Session *session,
+ const UA_Node *node) {
+ /* 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)
+ lifecycle->destructor(server,
+ &session->sessionId, session->sessionHandle,
+ &type->nodeId, type->context,
+ &node->nodeId, &context);
+ UA_Nodestore_release(server, type);
+ }
+ }
+
+ /* Call the global destructor */
+ if(server->config.nodeLifecycle.destructor)
+ server->config.nodeLifecycle.destructor(server, &session->sessionId,
+ session->sessionHandle,
+ &node->nodeId, context);
+}
+
+static void
+deleteNodeOperation(UA_Server *server, UA_Session *session, void *context,
+ const UA_DeleteNodesItem *item, UA_StatusCode *result);
+
+static void
+removeChildren(UA_Server *server, UA_Session *session,
+ const UA_Node *node) {
+ /* 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;
+ bd.nodeClassMask = UA_NODECLASS_OBJECT | UA_NODECLASS_VARIABLE | UA_NODECLASS_METHOD;
+ bd.resultMask = UA_BROWSERESULTMASK_NONE;
+
+ 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;
+
+ UA_DeleteNodesItem item;
+ item.deleteTargetReferences = true;
+
+ /* 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;
+ item.nodeId = rd->nodeId.nodeId;
+ UA_StatusCode retval;
+ deleteNodeOperation(server, session, NULL, &item, &retval);
+ }
+
+ UA_BrowseResult_deleteMembers(&br);
+}
+
+static void
+removeDeconstructedNode(UA_Server *server, UA_Session *session,
+ const UA_Node *node, UA_Boolean removeTargetRefs) {
+ /* Remove all children of the node */
+ removeChildren(server, session, node);
+
+ /* Remove references to the node (not the references going out, as the node
+ * will be deleted anyway) */
+ if(removeTargetRefs)
+ removeIncomingReferences(server, session, node);
+
+ /* Remove the node in the nodestore */
+ UA_Nodestore_remove(server, &node->nodeId);
+}
+
+static void
+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 &&
+ !server->config.accessControl.allowDeleteNode(server, &server->config.accessControl,
+ &session->sessionId, session->sessionHandle, item)) {
+ *result = UA_STATUSCODE_BADUSERACCESSDENIED;
+ return;
+ }
+
+ const UA_Node *node = UA_Nodestore_get(server, &item->nodeId);
+ if(!node) {
+ *result = UA_STATUSCODE_BADNODEIDUNKNOWN;
+ 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");
+ UA_Nodestore_release(server, node);
+ *result = UA_STATUSCODE_BADINTERNALERROR;
+ return;
+ }
+
+ /* TODO: Check if the information model consistency is violated */
+ /* TODO: Check if the node is a mandatory child of a parent */
+
+ deconstructNode(server, session, node);
+ removeDeconstructedNode(server, session, node, item->deleteTargetReferences);
+ UA_Nodestore_release(server, node);
+}
+
+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");
+
+ if(server->config.maxNodesPerNodeManagement != 0 &&
+ request->nodesToDeleteSize > server->config.maxNodesPerNodeManagement) {
+ response->responseHeader.serviceResult = UA_STATUSCODE_BADTOOMANYOPERATIONS;
+ return;
+ }
+
+ response->responseHeader.serviceResult =
+ UA_Server_processServiceOperations(server, session, (UA_ServiceOperation)deleteNodeOperation, NULL,
+ &request->nodesToDeleteSize, &UA_TYPES[UA_TYPES_DELETENODESITEM],
+ &response->resultsSize, &UA_TYPES[UA_TYPES_STATUSCODE]);
+}
+
+UA_StatusCode
+UA_Server_deleteNode(UA_Server *server, const UA_NodeId nodeId,
+ UA_Boolean deleteReferences) {
+ UA_DeleteNodesItem item;
+ item.deleteTargetReferences = deleteReferences;
+ item.nodeId = nodeId;
+ UA_StatusCode retval = UA_STATUSCODE_GOOD;
+ deleteNodeOperation(server, &server->adminSession, NULL, &item, &retval);
+ return retval;
+}
+
+/******************/
+/* Add References */
+/******************/
+
+static UA_StatusCode
+addOneWayReference(UA_Server *server, UA_Session *session,
+ UA_Node *node, const UA_AddReferencesItem *item) {
+ return UA_Node_addReference(node, item);
+}
+
+static UA_StatusCode
+deleteOneWayReference(UA_Server *server, UA_Session *session, UA_Node *node,
+ const UA_DeleteReferencesItem *item) {
+ return UA_Node_deleteReference(node, item);
+}
+
+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 */
+ if(session != &server->adminSession && server->config.accessControl.allowAddReference &&
+ !server->config.accessControl.allowAddReference(server, &server->config.accessControl,
+ &session->sessionId, session->sessionHandle, item)) {
+ *retval = UA_STATUSCODE_BADUSERACCESSDENIED;
+ return;
+ }
+
+ /* Currently no expandednodeids are allowed */
+ if(item->targetServerUri.length > 0) {
+ *retval = UA_STATUSCODE_BADNOTIMPLEMENTED;
+ return;
+ }
+
+ /* Add the first direction */
+ *retval = UA_Server_editNode(server, session, &item->sourceNodeId,
+ (UA_EditNodeCallback)addOneWayReference,
+ /* cast away const because callback uses const anyway */
+ (UA_AddReferencesItem *)(uintptr_t)item);
+ UA_Boolean firstExisted = UA_FALSE;
+ if(*retval == UA_STATUSCODE_BADDUPLICATEREFERENCENOTALLOWED) {
+ *retval = UA_STATUSCODE_GOOD;
+ firstExisted = UA_TRUE;
+ } else 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;
+ /* keep default secondItem.targetNodeClass = UA_NODECLASS_UNSPECIFIED */
+ *retval = UA_Server_editNode(server, session, &secondItem.sourceNodeId,
+ (UA_EditNodeCallback)addOneWayReference, &secondItem);
+
+ /* remove reference if the second direction failed */
+ UA_Boolean secondExisted = UA_FALSE;
+ if(*retval == UA_STATUSCODE_BADDUPLICATEREFERENCENOTALLOWED) {
+ *retval = UA_STATUSCODE_GOOD;
+ secondExisted = UA_TRUE;
+ } else 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 */
+ 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) {
+ UA_LOG_DEBUG_SESSION(server->config.logger, session,
+ "Processing AddReferencesRequest");
+
+ if(server->config.maxNodesPerNodeManagement != 0 &&
+ request->referencesToAddSize > server->config.maxNodesPerNodeManagement) {
+ response->responseHeader.serviceResult = UA_STATUSCODE_BADTOOMANYOPERATIONS;
+ return;
+ }
+
+ response->responseHeader.serviceResult =
+ UA_Server_processServiceOperations(server, session, (UA_ServiceOperation)Operation_addReference, NULL,
+ &request->referencesToAddSize, &UA_TYPES[UA_TYPES_ADDREFERENCESITEM],
+ &response->resultsSize, &UA_TYPES[UA_TYPES_STATUSCODE]);
+}
+
+UA_StatusCode
+UA_Server_addReference(UA_Server *server, const UA_NodeId sourceId,
+ const UA_NodeId refTypeId,
+ const UA_ExpandedNodeId targetId,
+ UA_Boolean isForward) {
+ UA_AddReferencesItem item;
+ UA_AddReferencesItem_init(&item);
+ item.sourceNodeId = sourceId;
+ item.referenceTypeId = refTypeId;
+ item.isForward = isForward;
+ item.targetNodeId = targetId;
+
+ UA_StatusCode retval = UA_STATUSCODE_GOOD;
+ Operation_addReference(server, &server->adminSession, NULL, &item, &retval);
+ return retval;
+}
+
+/*********************/
+/* Delete References */
+/*********************/
+
+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 &&
+ !server->config.accessControl.allowDeleteReference(server, &server->config.accessControl,
+ &session->sessionId, session->sessionHandle, item)) {
+ *retval = UA_STATUSCODE_BADUSERACCESSDENIED;
+ return;
+ }
+
+ // 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 */
+ (UA_DeleteReferencesItem *)(uintptr_t)item);
+ if(*retval != UA_STATUSCODE_GOOD)
+ return;
+
+ if(!item->deleteBidirectional || item->targetNodeId.serverIndex != 0)
+ return;
+
+ UA_DeleteReferencesItem secondItem;
+ UA_DeleteReferencesItem_init(&secondItem);
+ secondItem.isForward = !item->isForward;
+ secondItem.sourceNodeId = item->targetNodeId.nodeId;
+ secondItem.targetNodeId.nodeId = item->sourceNodeId;
+ secondItem.referenceTypeId = item->referenceTypeId;
+ *retval = UA_Server_editNode(server, session, &secondItem.sourceNodeId,
+ (UA_EditNodeCallback)deleteOneWayReference,
+ &secondItem);
+}
+
+void
+Service_DeleteReferences(UA_Server *server, UA_Session *session,
+ const UA_DeleteReferencesRequest *request,
+ UA_DeleteReferencesResponse *response) {
+ UA_LOG_DEBUG_SESSION(server->config.logger, session,
+ "Processing DeleteReferencesRequest");
+
+ if(server->config.maxNodesPerNodeManagement != 0 &&
+ request->referencesToDeleteSize > server->config.maxNodesPerNodeManagement) {
+ response->responseHeader.serviceResult = UA_STATUSCODE_BADTOOMANYOPERATIONS;
+ return;
+ }
+
+ response->responseHeader.serviceResult =
+ UA_Server_processServiceOperations(server, session, (UA_ServiceOperation)Operation_deleteReference, NULL,
+ &request->referencesToDeleteSize, &UA_TYPES[UA_TYPES_DELETEREFERENCESITEM],
+ &response->resultsSize, &UA_TYPES[UA_TYPES_STATUSCODE]);
+}
+
+UA_StatusCode
+UA_Server_deleteReference(UA_Server *server, const UA_NodeId sourceNodeId,
+ const UA_NodeId referenceTypeId, UA_Boolean isForward,
+ const UA_ExpandedNodeId targetNodeId,
+ UA_Boolean deleteBidirectional) {
+ UA_DeleteReferencesItem item;
+ item.sourceNodeId = sourceNodeId;
+ item.referenceTypeId = referenceTypeId;
+ item.isForward = isForward;
+ item.targetNodeId = targetNodeId;
+ item.deleteBidirectional = deleteBidirectional;
+
+ UA_StatusCode retval = UA_STATUSCODE_GOOD;
+ Operation_deleteReference(server, &server->adminSession, NULL, &item, &retval);
+ return retval;
+}
+
+/**********************/
+/* Set Value Callback */
+/**********************/
+
+static UA_StatusCode
+setValueCallback(UA_Server *server, UA_Session *session,
+ UA_VariableNode *node, const UA_ValueCallback *callback) {
+ if(node->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) {
+ return UA_Server_editNode(server, &server->adminSession, &nodeId,
+ (UA_EditNodeCallback)setValueCallback,
+ /* cast away const because callback uses const anyway */
+ (UA_ValueCallback *)(uintptr_t) &callback);
+}
+
+/***************************************************/
+/* Special Handling of Variables with Data Sources */
+/***************************************************/
+
+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,
+ void *nodeContext, UA_NodeId *outNewNodeId) {
+ UA_AddNodesItem item;
+ UA_AddNodesItem_init(&item);
+ item.nodeClass = UA_NODECLASS_VARIABLE;
+ item.requestedNewNodeId.nodeId = requestedNewNodeId;
+ item.browseName = browseName;
+ UA_ExpandedNodeId typeDefinitionId;
+ 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_NodeId newNodeId;
+ if(!outNewNodeId) {
+ newNodeId = UA_NODEID_NULL;
+ outNewNodeId = &newNodeId;
+ }
+
+ /* Create the node and add it to the nodestore */
+ UA_StatusCode retval = AddNode_raw(server, &server->adminSession, nodeContext, &item, outNewNodeId);
+ if(retval != UA_STATUSCODE_GOOD)
+ goto cleanup;
+
+ /* Set the data source */
+ retval = UA_Server_setVariableNode_dataSource(server, *outNewNodeId, dataSource);
+ if(retval != UA_STATUSCODE_GOOD)
+ goto cleanup;
+
+ /* Typecheck and add references to parent and type definition */
+ retval = AddNode_typeCheckAddRefs(server, &server->adminSession, outNewNodeId, &parentNodeId,
+ &referenceTypeId, &typeDefinition);
+ if(retval != UA_STATUSCODE_GOOD)
+ goto cleanup;
+
+ /* Call the constructors */
+ retval = Operation_addNode_finish(server, &server->adminSession, outNewNodeId);
+
+ cleanup:
+ if(outNewNodeId == &newNodeId)
+ UA_NodeId_deleteMembers(&newNodeId);
+
+ return retval;
+}
+
+static UA_StatusCode
+setDataSource(UA_Server *server, UA_Session *session,
+ UA_VariableNode* node, const UA_DataSource *dataSource) {
+ if(node->nodeClass != UA_NODECLASS_VARIABLE)
+ return UA_STATUSCODE_BADNODECLASSINVALID;
+ if(node->valueSource == UA_VALUESOURCE_DATA)
+ UA_DataValue_deleteMembers(&node->value.data.value);
+ node->value.dataSource = *dataSource;
+ node->valueSource = UA_VALUESOURCE_DATASOURCE;
+ return UA_STATUSCODE_GOOD;
+}
+
+UA_StatusCode
+UA_Server_setVariableNode_dataSource(UA_Server *server, const UA_NodeId nodeId,
+ const UA_DataSource dataSource) {
+ return UA_Server_editNode(server, &server->adminSession, &nodeId,
+ (UA_EditNodeCallback)setDataSource,
+ /* casting away const because callback casts it back anyway */
+ (UA_DataSource *) (uintptr_t)&dataSource);
+}
+
+/************************************/
+/* Special Handling of Method Nodes */
+/************************************/
+
+#ifdef UA_ENABLE_METHODCALLS
+
+static const UA_NodeId hasproperty = {0, UA_NODEIDTYPE_NUMERIC, {UA_NS0ID_HASPROPERTY}};
+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,
+ const UA_NodeId inputArgumentsRequestedNewNodeId,
+ UA_NodeId *inputArgumentsOutNewNodeId,
+ const size_t outputArgumentsSize, const UA_Argument *outputArguments,
+ const UA_NodeId outputArgumentsRequestedNewNodeId,
+ UA_NodeId *outputArgumentsOutNewNodeId) {
+ /* Browse to see which argument nodes exist */
+ UA_BrowseDescription bd;
+ UA_BrowseDescription_init(&bd);
+ bd.nodeId = nodeId;
+ bd.referenceTypeId = UA_NODEID_NUMERIC(0, UA_NS0ID_HASPROPERTY);
+ bd.includeSubtypes = false;
+ bd.browseDirection = UA_BROWSEDIRECTION_FORWARD;
+ bd.nodeClassMask = UA_NODECLASS_VARIABLE;
+ bd.resultMask = UA_BROWSERESULTMASK_BROWSENAME;
+
+ UA_BrowseResult br;
+ UA_BrowseResult_init(&br);
+ UA_UInt32 maxrefs = 0;
+ Operation_Browse(server, &server->adminSession, &maxrefs, &bd, &br);
+
+ UA_StatusCode retval = br.statusCode;
+ if(retval != UA_STATUSCODE_GOOD) {
+ UA_Server_deleteNode(server, nodeId, true);
+ UA_BrowseResult_deleteMembers(&br);
+ return retval;
+ }
+
+ /* Filter out the argument nodes */
+ UA_NodeId inputArgsId = UA_NODEID_NULL;
+ UA_NodeId outputArgsId = UA_NODEID_NULL;
+ const UA_QualifiedName inputArgsName = UA_QUALIFIEDNAME(0, "InputArguments");
+ const UA_QualifiedName outputArgsName = UA_QUALIFIEDNAME(0, "OutputArguments");
+ for(size_t i = 0; i < br.referencesSize; i++) {
+ UA_ReferenceDescription *rd = &br.references[i];
+ if(rd->browseName.namespaceIndex == 0 &&
+ UA_String_equal(&rd->browseName.name, &inputArgsName.name))
+ inputArgsId = rd->nodeId.nodeId;
+ else if(rd->browseName.namespaceIndex == 0 &&
+ UA_String_equal(&rd->browseName.name, &outputArgsName.name))
+ outputArgsId = rd->nodeId.nodeId;
+ }
+
+ /* Add the Input Arguments VariableNode */
+ if(inputArgumentsSize > 0 && UA_NodeId_isNull(&inputArgsId)) {
+ UA_VariableAttributes attr = UA_VariableAttributes_default;
+ char *name = "InputArguments";
+ attr.displayName = UA_LOCALIZEDTEXT("", name);
+ attr.dataType = UA_TYPES[UA_TYPES_ARGUMENT].typeId;
+ attr.valueRank = UA_VALUERANK_ONE_DIMENSION;
+ UA_UInt32 inputArgsSize32 = (UA_UInt32)inputArgumentsSize;
+ attr.arrayDimensions = &inputArgsSize32;
+ attr.arrayDimensionsSize = 1;
+ UA_Variant_setArray(&attr.value, (void*)(uintptr_t) inputArguments,
+ inputArgumentsSize, &UA_TYPES[UA_TYPES_ARGUMENT]);
+ retval |= UA_Server_addVariableNode(server, inputArgumentsRequestedNewNodeId, nodeId,
+ hasproperty, UA_QUALIFIEDNAME(0, name),
+ propertytype, attr, NULL, &inputArgsId);
+ }
+
+ /* Add the Output Arguments VariableNode */
+ if(outputArgumentsSize > 0 && UA_NodeId_isNull(&outputArgsId)) {
+ UA_VariableAttributes attr = UA_VariableAttributes_default;
+ char *name = "OutputArguments";
+ attr.displayName = UA_LOCALIZEDTEXT("", name);
+ attr.dataType = UA_TYPES[UA_TYPES_ARGUMENT].typeId;
+ attr.valueRank = UA_VALUERANK_ONE_DIMENSION;
+ UA_UInt32 outputArgsSize32 = (UA_UInt32)outputArgumentsSize;
+ attr.arrayDimensions = &outputArgsSize32;
+ attr.arrayDimensionsSize = 1;
+ UA_Variant_setArray(&attr.value, (void*)(uintptr_t) outputArguments,
+ outputArgumentsSize, &UA_TYPES[UA_TYPES_ARGUMENT]);
+ retval |= UA_Server_addVariableNode(server, outputArgumentsRequestedNewNodeId, nodeId,
+ hasproperty, UA_QUALIFIEDNAME(0, name),
+ propertytype, attr, NULL, &outputArgsId);
+ }
+
+ retval |= UA_Server_setMethodNode_callback(server, nodeId, method);
+
+ /* Call finish to add the parent reference */
+ retval |= Operation_addNode_finish(server, &server->adminSession, &nodeId);
+
+ if(retval != UA_STATUSCODE_GOOD) {
+ UA_Server_deleteNode(server, nodeId, true);
+ UA_Server_deleteNode(server, inputArgsId, true);
+ UA_Server_deleteNode(server, outputArgsId, true);
+ } else {
+ if(inputArgumentsOutNewNodeId != NULL) {
+ UA_NodeId_copy(&inputArgsId, inputArgumentsOutNewNodeId);
+ }
+ if(outputArgumentsOutNewNodeId != NULL) {
+ UA_NodeId_copy(&outputArgsId, outputArgumentsOutNewNodeId);
+ }
+ }
+ UA_BrowseResult_deleteMembers(&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) {
+ return UA_Server_addMethodNodeEx_finish(server, nodeId, method,
+ inputArgumentsSize, inputArguments, UA_NODEID_NULL, NULL,
+ outputArgumentsSize, outputArguments, UA_NODEID_NULL, NULL);
+}
+
+UA_StatusCode
+UA_Server_addMethodNodeEx(UA_Server *server, const UA_NodeId requestedNewNodeId,
+ const UA_NodeId parentNodeId,
+ const UA_NodeId referenceTypeId,
+ const UA_QualifiedName browseName,
+ const UA_MethodAttributes attr, UA_MethodCallback method,
+ size_t inputArgumentsSize, const UA_Argument *inputArguments,
+ const UA_NodeId inputArgumentsRequestedNewNodeId,
+ UA_NodeId *inputArgumentsOutNewNodeId,
+ size_t outputArgumentsSize, const UA_Argument *outputArguments,
+ const UA_NodeId outputArgumentsRequestedNewNodeId,
+ UA_NodeId *outputArgumentsOutNewNodeId,
+ void *nodeContext, UA_NodeId *outNewNodeId) {
+ UA_AddNodesItem item;
+ UA_AddNodesItem_init(&item);
+ 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_NodeId newId;
+ if(!outNewNodeId) {
+ UA_NodeId_init(&newId);
+ outNewNodeId = &newId;
+ }
+
+ UA_StatusCode retval = Operation_addNode_begin(server, &server->adminSession, nodeContext,
+ &item, &parentNodeId, &referenceTypeId, outNewNodeId);
+ if(retval != UA_STATUSCODE_GOOD)
+ return retval;
+
+ retval = UA_Server_addMethodNodeEx_finish(server, *outNewNodeId, method,
+ inputArgumentsSize, inputArguments,
+ inputArgumentsRequestedNewNodeId,
+ inputArgumentsOutNewNodeId,
+ outputArgumentsSize, outputArguments,
+ outputArgumentsRequestedNewNodeId,
+ outputArgumentsOutNewNodeId);
+
+ if(outNewNodeId == &newId)
+ UA_NodeId_deleteMembers(&newId);
+ return retval;
+}
+
+static UA_StatusCode
+editMethodCallback(UA_Server *server, UA_Session* session,
+ UA_Node* node, void* handle) {
+ if(node->nodeClass != UA_NODECLASS_METHOD)
+ return UA_STATUSCODE_BADNODECLASSINVALID;
+ UA_MethodNode *mnode = (UA_MethodNode*) node;
+ mnode->method = (UA_MethodCallback)(uintptr_t)handle;
+ return UA_STATUSCODE_GOOD;
+}
+
+UA_StatusCode
+UA_Server_setMethodNode_callback(UA_Server *server,
+ const UA_NodeId methodNodeId,
+ UA_MethodCallback methodCallback) {
+ return UA_Server_editNode(server, &server->adminSession, &methodNodeId,
+ (UA_EditNodeCallback)editMethodCallback,
+ (void*)(uintptr_t)methodCallback);
+}
+
+#endif
+
+/************************/
+/* Lifecycle Management */
+/************************/
+
+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;
+ }
+
+ return UA_STATUSCODE_BADNODECLASSINVALID;
+}
+
+UA_StatusCode
+UA_Server_setNodeTypeLifecycle(UA_Server *server, UA_NodeId nodeId,
+ UA_NodeTypeLifecycle lifecycle) {
+ return UA_Server_editNode(server, &server->adminSession, &nodeId,
+ (UA_EditNodeCallback)setNodeTypeLifecycle,
+ &lifecycle);
+}
+
+/*********************************** amalgamated original file "/home/jvoe/open62541/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
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * Copyright 2017 (c) Stefan Profanter, fortiss GmbH
+ * Copyright 2017 (c) Julius Pfrommer, Fraunhofer IOSB
+ * Copyright 2017 (c) Thomas Stalder, Blue Time Concept SA
+ */
+
+/* Enable POSIX features */
+#if !defined(_XOPEN_SOURCE) && !defined(_WRS_KERNEL)
+# define _XOPEN_SOURCE 600
+#endif
+#ifndef _DEFAULT_SOURCE
+# define _DEFAULT_SOURCE
+#endif
+/* On older systems we need to define _BSD_SOURCE.
+ * _DEFAULT_SOURCE is an alias for that. */
+#ifndef _BSD_SOURCE
+# define _BSD_SOURCE
+#endif
+
+
+#if defined(UA_ENABLE_DISCOVERY) && defined(UA_ENABLE_DISCOVERY_MULTICAST)
+
+#ifdef _MSC_VER
+# ifndef UNDER_CE
+# include <io.h> //access
+# define access _access
+# endif
+#else
+# include <unistd.h> //access
+# include <sys/time.h> // struct timeval
+#endif
+
+#include <fcntl.h>
+#include <errno.h>
+#ifdef _WIN32
+# define CLOSESOCKET(S) closesocket((SOCKET)S)
+# define errno__ WSAGetLastError()
+#else
+# define CLOSESOCKET(S) close(S)
+# define errno__ errno
+#endif
+
+
+#ifdef UA_ENABLE_MULTITHREADING
+
+static void *
+multicastWorkerLoop(UA_Server *server) {
+ struct timeval next_sleep = {.tv_sec = 0, .tv_usec = 0};
+ volatile UA_Boolean *running = &server->mdnsRunning;
+ fd_set fds;
+
+ while(*running) {
+ FD_ZERO(&fds);
+ FD_SET(server->mdnsSocket, &fds);
+ select(server->mdnsSocket + 1, &fds, 0, 0, &next_sleep);
+
+ if(!*running)
+ break;
+
+ unsigned short retVal =
+ mdnsd_step(server->mdnsDaemon, server->mdnsSocket,
+ FD_ISSET(server->mdnsSocket, &fds), true, &next_sleep);
+ if(retVal == 1) {
+ UA_LOG_SOCKET_ERRNO_WRAP(
+ UA_LOG_ERROR(server->config.logger, UA_LOGCATEGORY_SERVER,
+ "Multicast error: Can not read from socket. %s", errno_str));
+ break;
+ } else if (retVal == 2) {
+ UA_LOG_SOCKET_ERRNO_WRAP(
+ UA_LOG_ERROR(server->config.logger, UA_LOGCATEGORY_SERVER,
+ "Multicast error: Can not write to socket. %s", errno_str));
+ break;
+ }
+ }
+ return NULL;
+}
+
+static UA_StatusCode
+multicastListenStart(UA_Server* server) {
+ int err = pthread_create(&server->mdnsThread, NULL,
+ (void* (*)(void*))multicastWorkerLoop, server);
+ if(err != 0) {
+ UA_LOG_ERROR(server->config.logger, UA_LOGCATEGORY_SERVER,
+ "Multicast error: Can not create multicast thread.");
+ return UA_STATUSCODE_BADUNEXPECTEDERROR;
+ }
+ return UA_STATUSCODE_GOOD;
+}
+
+static UA_StatusCode
+multicastListenStop(UA_Server* server) {
+ mdnsd_shutdown(server->mdnsDaemon);
+ // wake up select
+ write(server->mdnsSocket, "\0", 1);
+ if(pthread_join(server->mdnsThread, NULL)) {
+ UA_LOG_ERROR(server->config.logger, UA_LOGCATEGORY_SERVER,
+ "Multicast error: Can not stop thread.");
+ return UA_STATUSCODE_BADUNEXPECTEDERROR;
+ }
+ return UA_STATUSCODE_BADNOTIMPLEMENTED;
+}
+
+# endif /* UA_ENABLE_MULTITHREADING */
+
+static UA_StatusCode
+addMdnsRecordForNetworkLayer(UA_Server *server, const UA_String *appName,
+ const UA_ServerNetworkLayer* nl) {
+ UA_String hostname = UA_STRING_NULL;
+ UA_UInt16 port = 4840;
+ UA_String path = UA_STRING_NULL;
+ UA_StatusCode retval = UA_parseEndpointUrl(&nl->discoveryUrl, &hostname,
+ &port, &path);
+ if(retval != UA_STATUSCODE_GOOD) {
+ UA_LOG_WARNING(server->config.logger, UA_LOGCATEGORY_NETWORK,
+ "Server url is invalid: %.*s",
+ (int)nl->discoveryUrl.length, nl->discoveryUrl.data);
+ return retval;
+ }
+ UA_Discovery_addRecord(server, appName, &hostname, port,
+ &path, UA_DISCOVERY_TCP, UA_TRUE,
+ server->config.serverCapabilities,
+ &server->config.serverCapabilitiesSize);
+ return UA_STATUSCODE_GOOD;
+}
+
+void startMulticastDiscoveryServer(UA_Server *server) {
+ UA_String *appName = &server->config.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);
+
+# ifdef UA_ENABLE_MULTITHREADING
+ multicastListenStart(server);
+# endif
+}
+
+void stopMulticastDiscoveryServer(UA_Server *server) {
+ char hostname[256];
+ if(gethostname(hostname, 255) == 0) {
+ UA_String hnString = UA_STRING(hostname);
+ UA_Discovery_removeRecord(server, &server->config.mdnsServerName,
+ &hnString, 4840, UA_TRUE);
+ } else {
+ UA_LOG_ERROR(server->config.logger, UA_LOGCATEGORY_SERVER,
+ "Could not get hostname for multicast discovery.");
+ }
+
+# ifdef UA_ENABLE_MULTITHREADING
+ multicastListenStop(server);
+# else
+ // send out last package with TTL = 0
+ iterateMulticastDiscoveryServer(server, NULL, UA_FALSE);
+# endif
+}
+
+/* All filter criteria must be fulfilled */
+static UA_Boolean
+filterServerRecord(size_t serverCapabilityFilterSize, UA_String *serverCapabilityFilter,
+ serverOnNetwork_list_entry* current) {
+ 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;
+ }
+ return true;
+}
+
+void Service_FindServersOnNetwork(UA_Server *server, UA_Session *session,
+ const UA_FindServersOnNetworkRequest *request,
+ UA_FindServersOnNetworkResponse *response) {
+ /* Set LastCounterResetTime */
+ UA_DateTime_copy(&server->serverOnNetworkRecordIdLastReset,
+ &response->lastCounterResetTime);
+
+ /* Compute the max number of records to return */
+ UA_UInt32 recordCount = 0;
+ if(request->startingRecordId < server->serverOnNetworkRecordIdCounter)
+ recordCount = server->serverOnNetworkRecordIdCounter - request->startingRecordId;
+ if(request->maxRecordsToReturn && recordCount > request->maxRecordsToReturn)
+ recordCount = UA_MIN(recordCount, request->maxRecordsToReturn);
+ if(recordCount == 0) {
+ response->serversSize = 0;
+ return;
+ }
+
+ /* Iterate over all records and add to filtered list */
+ UA_UInt32 filteredCount = 0;
+ UA_STACKARRAY(UA_ServerOnNetwork*, filtered, recordCount);
+ serverOnNetwork_list_entry* current;
+ LIST_FOREACH(current, &server->serverOnNetwork, pointers) {
+ if(filteredCount >= recordCount)
+ break;
+ if(current->serverOnNetwork.recordId < request->startingRecordId)
+ continue;
+ if(!filterServerRecord(request->serverCapabilityFilterSize,
+ request->serverCapabilityFilter, current))
+ continue;
+ filtered[filteredCount++] = &current->serverOnNetwork;
+ }
+
+ if(filteredCount == 0)
+ return;
+
+ /* Allocate the array for the response */
+ response->servers =
+ (UA_ServerOnNetwork*)UA_malloc(sizeof(UA_ServerOnNetwork)*filteredCount);
+ if(!response->servers) {
+ response->responseHeader.serviceResult = UA_STATUSCODE_BADOUTOFMEMORY;
+ return;
+ }
+ response->serversSize = filteredCount;
+
+ /* Copy the server names */
+ for(size_t i = 0; i < filteredCount; i++)
+ UA_ServerOnNetwork_copy(filtered[i], &response->servers[filteredCount-i-1]);
+}
+
+void
+UA_Discovery_update_MdnsForDiscoveryUrl(UA_Server *server, const UA_String *serverName,
+ const UA_MdnsDiscoveryConfiguration *mdnsConfig,
+ const UA_String *discoveryUrl,
+ UA_Boolean isOnline, UA_Boolean updateTxt) {
+ UA_String hostname = UA_STRING_NULL;
+ UA_UInt16 port = 4840;
+ UA_String path = UA_STRING_NULL;
+ UA_StatusCode retval = UA_parseEndpointUrl(discoveryUrl, &hostname, &port, &path);
+ if(retval != UA_STATUSCODE_GOOD) {
+ UA_LOG_WARNING(server->config.logger, UA_LOGCATEGORY_NETWORK,
+ "Server url invalid: %.*s",
+ (int)discoveryUrl->length, discoveryUrl->data);
+ return;
+ }
+
+ if(!isOnline) {
+ UA_StatusCode removeRetval =
+ UA_Discovery_removeRecord(server, serverName, &hostname,
+ port, updateTxt);
+ if(removeRetval != UA_STATUSCODE_GOOD)
+ UA_LOG_WARNING(server->config.logger, UA_LOGCATEGORY_SERVER,
+ "Could not remove mDNS record for hostname %.*s.",
+ (int)serverName->length, serverName->data);
+ return;
+ }
+
+ UA_String *capabilities = NULL;
+ size_t capabilitiesSize = 0;
+ if(mdnsConfig) {
+ capabilities = mdnsConfig->serverCapabilities;
+ capabilitiesSize = mdnsConfig->serverCapabilitiesSize;
+ }
+
+ UA_StatusCode addRetval =
+ UA_Discovery_addRecord(server, serverName, &hostname,
+ port, &path, UA_DISCOVERY_TCP, updateTxt,
+ capabilities, &capabilitiesSize);
+ if(addRetval != UA_STATUSCODE_GOOD)
+ UA_LOG_WARNING(server->config.logger, UA_LOGCATEGORY_SERVER,
+ "Could not add mDNS record for hostname %.*s.",
+ (int)serverName->length, serverName->data);
+}
+
+void
+UA_Server_setServerOnNetworkCallback(UA_Server *server,
+ UA_Server_serverOnNetworkCallback cb,
+ void* data) {
+ server->serverOnNetworkCallback = cb;
+ server->serverOnNetworkCallbackData = data;
+}
+
+static void
+socket_mdns_set_nonblocking(int sockfd) {
+#ifdef _WIN32
+ u_long iMode = 1;
+ ioctlsocket(sockfd, FIONBIO, &iMode);
+#else
+ int opts = fcntl(sockfd, F_GETFL);
+ fcntl(sockfd, F_SETFL, opts|O_NONBLOCK);
+#endif
+}
+
+/* Create multicast 224.0.0.251:5353 socket */
+#ifdef _WIN32
+static SOCKET
+#else
+static int
+#endif
+discovery_createMulticastSocket(void) {
+#ifdef _WIN32
+ SOCKET s;
+#else
+ int s;
+#endif
+ int flag = 1, ittl = 255;
+ struct sockaddr_in in;
+ struct ip_mreq mc;
+ char ttl = (char)255; // publish to complete net, not only subnet. See:
+ // https://docs.oracle.com/cd/E23824_01/html/821-1602/sockets-137.html
+
+ memset(&in, 0, sizeof(in));
+ in.sin_family = AF_INET;
+ in.sin_port = htons(5353);
+ in.sin_addr.s_addr = 0;
+
+#ifdef _WIN32
+ if((s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == INVALID_SOCKET)
+ return INVALID_SOCKET;
+#else
+ if((s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0)
+ return -1;
+#endif
+
+#ifdef SO_REUSEPORT
+ setsockopt(s, SOL_SOCKET, SO_REUSEPORT, (char *)&flag, sizeof(flag));
+#endif
+ setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char *)&flag, sizeof(flag));
+ if(bind(s, (struct sockaddr *)&in, sizeof(in))) {
+ CLOSESOCKET(s);
+#ifdef _WIN32
+ return INVALID_SOCKET;
+#else
+ return -1;
+#endif
+ }
+
+ mc.imr_multiaddr.s_addr = inet_addr("224.0.0.251");
+ mc.imr_interface.s_addr = htonl(INADDR_ANY);
+ setsockopt(s, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char*)&mc, sizeof(mc));
+ setsockopt(s, IPPROTO_IP, IP_MULTICAST_TTL, (char*)&ttl, sizeof(ttl));
+ setsockopt(s, IPPROTO_IP, IP_MULTICAST_TTL, (char*)&ittl, sizeof(ittl));
+
+ socket_mdns_set_nonblocking(s);
+ return s;
+}
+
+
+UA_StatusCode
+initMulticastDiscoveryServer(UA_Server* server) {
+ server->mdnsDaemon = mdnsd_new(QCLASS_IN, 1000);
+#ifdef _WIN32
+ WORD wVersionRequested = MAKEWORD(2, 2);
+ WSADATA wsaData;
+ WSAStartup(wVersionRequested, &wsaData);
+#endif
+
+#ifdef _WIN32
+ if((server->mdnsSocket = discovery_createMulticastSocket()) == INVALID_SOCKET) {
+#else
+ if((server->mdnsSocket = discovery_createMulticastSocket()) < 0) {
+#endif
+ UA_LOG_SOCKET_ERRNO_WRAP(
+ UA_LOG_ERROR(server->config.logger, UA_LOGCATEGORY_SERVER,
+ "Could not create multicast socket. Error: %s", errno_str));
+ return UA_STATUSCODE_BADUNEXPECTEDERROR;
+ }
+ mdnsd_register_receive_callback(server->mdnsDaemon,
+ mdns_record_received, server);
+ return UA_STATUSCODE_GOOD;
+}
+
+void destroyMulticastDiscoveryServer(UA_Server* server) {
+ mdnsd_shutdown(server->mdnsDaemon);
+ mdnsd_free(server->mdnsDaemon);
+#ifdef _WIN32
+ if(server->mdnsSocket != INVALID_SOCKET) {
+#else
+ if(server->mdnsSocket >= 0) {
+#endif
+ CLOSESOCKET(server->mdnsSocket);
+#ifdef _WIN32
+ server->mdnsSocket = INVALID_SOCKET;
+#else
+ server->mdnsSocket = -1;
+#endif
+ }
+}
+
+static void
+UA_Discovery_multicastConflict(char *name, int type, void *arg) {
+ // cppcheck-suppress unreadVariable
+ UA_Server *server = (UA_Server*) arg;
+ UA_LOG_ERROR(server->config.logger, UA_LOGCATEGORY_SERVER,
+ "Multicast DNS name conflict detected: "
+ "'%s' for type %d", name, type);
+}
+
+/* Create a service domain with the format [servername]-[hostname]._opcua-tcp._tcp.local. */
+static void
+createFullServiceDomain(char *outServiceDomain, size_t maxLen,
+ const UA_String *servername, const UA_String *hostname) {
+ size_t hostnameLen = hostname->length;
+ size_t servernameLen = servername->length;
+
+ maxLen -= 24; /* the length we have remaining before the opc ua postfix and
+ * the trailing zero */
+
+ /* Can we use hostname and servername with full length? */
+ if(hostnameLen + servernameLen + 1 > maxLen) {
+ if(servernameLen + 2 > maxLen) {
+ servernameLen = maxLen;
+ hostnameLen = 0;
+ } else {
+ hostnameLen = maxLen - servernameLen - 1;
+ }
+ }
+
+ /* Copy into outServiceDomain */
+ size_t offset = 0;
+ memcpy(&outServiceDomain[offset], servername->data, servernameLen);
+ offset += servernameLen;
+ if(hostnameLen > 0) {
+ memcpy(&outServiceDomain[offset], "-", 1);
+ ++offset;
+ memcpy(&outServiceDomain[offset], hostname->data, hostnameLen);
+ offset += hostnameLen;
+ }
+ memcpy(&outServiceDomain[offset], "._opcua-tcp._tcp.local.", 23);
+ offset += 23;
+ outServiceDomain[offset] = 0;
+}
+
+/* Check if mDNS already has an entry for given hostname and port combination */
+static UA_Boolean
+UA_Discovery_recordExists(UA_Server* server, const char* fullServiceDomain,
+ unsigned short port, const UA_DiscoveryProtocol protocol) {
+ // [servername]-[hostname]._opcua-tcp._tcp.local. 86400 IN SRV 0 5 port [hostname].
+ mdns_record_t *r = mdnsd_get_published(server->mdnsDaemon, fullServiceDomain);
+ while(r) {
+ const mdns_answer_t *data = mdnsd_record_data(r);
+ if(data->type == QTYPE_SRV && (port == 0 || data->srv.port == port))
+ return UA_TRUE;
+ r = mdnsd_record_next(r);
+ }
+ return UA_FALSE;
+}
+
+static int
+discovery_multicastQueryAnswer(mdns_answer_t *a, void *arg) {
+ UA_Server *server = (UA_Server*) arg;
+ if(a->type != QTYPE_PTR)
+ return 0;
+
+ if(a->rdname == NULL)
+ return 0;
+
+ /* Skip, if we already know about this server */
+ UA_Boolean exists =
+ UA_Discovery_recordExists(server, a->rdname, 0, UA_DISCOVERY_TCP);
+ if(exists == UA_TRUE)
+ return 0;
+
+ if(mdnsd_has_query(server->mdnsDaemon, a->rdname))
+ return 0;
+
+ UA_LOG_DEBUG(server->config.logger, UA_LOGCATEGORY_SERVER,
+ "mDNS send query for: %s SRV&TXT %s", a->name, a->rdname);
+
+ mdnsd_query(server->mdnsDaemon, a->rdname, QTYPE_SRV,
+ discovery_multicastQueryAnswer, server);
+ mdnsd_query(server->mdnsDaemon, a->rdname, QTYPE_TXT,
+ discovery_multicastQueryAnswer, server);
+ return 0;
+}
+
+UA_StatusCode
+UA_Discovery_multicastQuery(UA_Server* server) {
+ mdnsd_query(server->mdnsDaemon, "_opcua-tcp._tcp.local.",
+ QTYPE_PTR,discovery_multicastQueryAnswer, server);
+ return UA_STATUSCODE_GOOD;
+}
+
+UA_StatusCode
+UA_Discovery_addRecord(UA_Server *server, const UA_String *servername,
+ const UA_String *hostname, UA_UInt16 port,
+ const UA_String *path, const UA_DiscoveryProtocol protocol,
+ UA_Boolean createTxt, const UA_String* capabilites,
+ size_t *capabilitiesSize) {
+ if(!capabilitiesSize || (*capabilitiesSize > 0 && !capabilites))
+ return UA_STATUSCODE_BADINVALIDARGUMENT;
+
+ size_t hostnameLen = hostname->length;
+ size_t servernameLen = servername->length;
+ if(hostnameLen == 0 || servernameLen == 0)
+ return UA_STATUSCODE_BADOUTOFRANGE;
+
+ // use a limit for the hostname length to make sure full string fits into 63
+ // chars (limited by DNS spec)
+ if(hostnameLen+servernameLen + 1 > 63) { // include dash between servername-hostname
+ UA_LOG_WARNING(server->config.logger, UA_LOGCATEGORY_SERVER,
+ "Multicast DNS: Combination of hostname+servername exceeds "
+ "maximum of 62 chars. It will be truncated.");
+ } else if(hostnameLen > 63) {
+ UA_LOG_WARNING(server->config.logger, UA_LOGCATEGORY_SERVER,
+ "Multicast DNS: Hostname length exceeds maximum of 63 chars. "
+ "It will be truncated.");
+ }
+
+ if(!server->mdnsMainSrvAdded) {
+ mdns_record_t *r =
+ mdnsd_shared(server->mdnsDaemon, "_services._dns-sd._udp.local.",
+ QTYPE_PTR, 600);
+ mdnsd_set_host(server->mdnsDaemon, r, "_opcua-tcp._tcp.local.");
+ server->mdnsMainSrvAdded = UA_TRUE;
+ }
+
+ // [servername]-[hostname]._opcua-tcp._tcp.local.
+ char fullServiceDomain[63+24];
+ createFullServiceDomain(fullServiceDomain, 63+24, servername, hostname);
+
+ UA_Boolean exists = UA_Discovery_recordExists(server, fullServiceDomain, port, protocol);
+ if(exists == UA_TRUE)
+ return UA_STATUSCODE_GOOD;
+
+ UA_LOG_INFO(server->config.logger, UA_LOGCATEGORY_SERVER,
+ "Multicast DNS: add record for domain: %s", fullServiceDomain);
+
+ // _services._dns-sd._udp.local. PTR _opcua-tcp._tcp.local
+
+ // check if there is already a PTR entry for the given service.
+
+ // _opcua-tcp._tcp.local. PTR [servername]-[hostname]._opcua-tcp._tcp.local.
+ mdns_record_t *r = mdns_find_record(server->mdnsDaemon, QTYPE_PTR,
+ "_opcua-tcp._tcp.local.", fullServiceDomain);
+ if(!r) {
+ r = mdnsd_shared(server->mdnsDaemon, "_opcua-tcp._tcp.local.", QTYPE_PTR, 600);
+ mdnsd_set_host(server->mdnsDaemon, r, fullServiceDomain);
+ }
+
+ /* The first 63 characters of the hostname (or less) */
+ size_t maxHostnameLen = UA_MIN(hostnameLen, 63);
+ char localDomain[65];
+ memcpy(localDomain, hostname->data, maxHostnameLen);
+ localDomain[maxHostnameLen] = '.';
+ localDomain[maxHostnameLen+1] = '\0';
+
+ // [servername]-[hostname]._opcua-tcp._tcp.local. 86400 IN SRV 0 5 port [hostname].
+ r = mdnsd_unique(server->mdnsDaemon, fullServiceDomain, QTYPE_SRV, 600,
+ UA_Discovery_multicastConflict, server);
+ mdnsd_set_srv(server->mdnsDaemon, r, 0, 0, port, localDomain);
+
+ // A/AAAA record for all ip addresses.
+ // [servername]-[hostname]._opcua-tcp._tcp.local. A [ip].
+ // [hostname]. A [ip].
+ mdns_set_address_record(server, fullServiceDomain, localDomain);
+
+ // TXT record: [servername]-[hostname]._opcua-tcp._tcp.local. TXT path=/ caps=NA,DA,...
+ UA_STACKARRAY(char, pathChars, path->length + 1);
+ if(createTxt) {
+ memcpy(pathChars, path->data, path->length);
+ pathChars[path->length] = 0;
+ mdns_create_txt(server, fullServiceDomain, pathChars, capabilites,
+ capabilitiesSize, UA_Discovery_multicastConflict);
+ }
+
+ return UA_STATUSCODE_GOOD;
+}
+
+UA_StatusCode
+UA_Discovery_removeRecord(UA_Server *server, const UA_String *servername,
+ const UA_String *hostname, UA_UInt16 port,
+ UA_Boolean removeTxt) {
+ // use a limit for the hostname length to make sure full string fits into 63
+ // chars (limited by DNS spec)
+ size_t hostnameLen = hostname->length;
+ size_t servernameLen = servername->length;
+ if(hostnameLen == 0 || servernameLen == 0)
+ return UA_STATUSCODE_BADOUTOFRANGE;
+
+ if(hostnameLen+servernameLen+1 > 63) { // include dash between servername-hostname
+ UA_LOG_WARNING(server->config.logger, UA_LOGCATEGORY_SERVER,
+ "Multicast DNS: Combination of hostname+servername exceeds "
+ "maximum of 62 chars. It will be truncated.");
+ }
+
+ // [servername]-[hostname]._opcua-tcp._tcp.local.
+ char fullServiceDomain[63 + 24];
+ createFullServiceDomain(fullServiceDomain, 63+24, servername, hostname);
+
+ UA_LOG_INFO(server->config.logger, UA_LOGCATEGORY_SERVER,
+ "Multicast DNS: remove record for domain: %s", fullServiceDomain);
+
+ // _opcua-tcp._tcp.local. PTR [servername]-[hostname]._opcua-tcp._tcp.local.
+ mdns_record_t *r = mdns_find_record(server->mdnsDaemon, QTYPE_PTR,
+ "_opcua-tcp._tcp.local.", fullServiceDomain);
+ if(!r) {
+ UA_LOG_WARNING(server->config.logger, UA_LOGCATEGORY_SERVER,
+ "Multicast DNS: could not remove record. "
+ "PTR Record not found for domain: %s", fullServiceDomain);
+ return UA_STATUSCODE_BADNOTHINGTODO;
+ }
+ mdnsd_done(server->mdnsDaemon, r);
+
+ // looks for [servername]-[hostname]._opcua-tcp._tcp.local. 86400 IN SRV 0 5 port hostname.local.
+ // and TXT record: [servername]-[hostname]._opcua-tcp._tcp.local. TXT path=/ caps=NA,DA,...
+ // and A record: [servername]-[hostname]._opcua-tcp._tcp.local. A [ip]
+ mdns_record_t *r2 = mdnsd_get_published(server->mdnsDaemon, fullServiceDomain);
+ if(!r2) {
+ UA_LOG_WARNING(server->config.logger, UA_LOGCATEGORY_SERVER,
+ "Multicast DNS: could not remove record. Record not "
+ "found for domain: %s", fullServiceDomain);
+ return UA_STATUSCODE_BADNOTHINGTODO;
+ }
+
+ while(r2) {
+ const mdns_answer_t *data = mdnsd_record_data(r2);
+ mdns_record_t *next = mdnsd_record_next(r2);
+ if((removeTxt && data->type == QTYPE_TXT) ||
+ (removeTxt && data->type == QTYPE_A) ||
+ data->srv.port == port) {
+ mdnsd_done(server->mdnsDaemon, r2);
+ }
+ r2 = next;
+ }
+
+ return UA_STATUSCODE_GOOD;
+}
+
+UA_StatusCode
+iterateMulticastDiscoveryServer(UA_Server* server, UA_DateTime *nextRepeat,
+ UA_Boolean processIn) {
+ struct timeval next_sleep = { 0, 0 };
+ unsigned short retval = mdnsd_step(server->mdnsDaemon, server->mdnsSocket,
+ processIn, true, &next_sleep);
+ if(retval == 1) {
+ UA_LOG_SOCKET_ERRNO_WRAP(
+ UA_LOG_ERROR(server->config.logger, UA_LOGCATEGORY_SERVER,
+ "Multicast error: Can not read from socket. %s", errno_str));
+ return UA_STATUSCODE_BADNOCOMMUNICATION;
+ } else if(retval == 2) {
+ UA_LOG_SOCKET_ERRNO_WRAP(
+ UA_LOG_ERROR(server->config.logger, UA_LOGCATEGORY_SERVER,
+ "Multicast error: Can not write to socket. %s", errno_str));
+ return UA_STATUSCODE_BADNOCOMMUNICATION;
+ }
+
+ if(nextRepeat)
+ *nextRepeat = UA_DateTime_now() +
+ (UA_DateTime)((next_sleep.tv_sec * UA_DATETIME_SEC) +
+ (next_sleep.tv_usec * UA_DATETIME_USEC));
+ return UA_STATUSCODE_GOOD;
+}
+
+#endif /* defined(UA_ENABLE_DISCOVERY) && defined(UA_ENABLE_DISCOVERY_MULTICAST) */
+
+/*********************************** amalgamated original file "/home/jvoe/open62541/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
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * Copyright 2015-2017 (c) Julius Pfrommer, Fraunhofer IOSB
+ * Copyright 2015-2016 (c) Sten Grüner
+ * Copyright 2015-2016 (c) Chris Iatrou
+ * Copyright 2015 (c) hfaham
+ * Copyright 2015-2017 (c) Florian Palm
+ * Copyright 2017-2018 (c) Thomas Stalder, Blue Time Concept SA
+ * Copyright 2015 (c) Holger Jeromin
+ * Copyright 2015 (c) Oleksiy Vasylyev
+ * Copyright 2016 (c) TorbenD
+ * Copyright 2017 (c) Stefan Profanter, fortiss GmbH
+ * Copyright 2016 (c) Lykurg
+ * Copyright 2017 (c) Mark Giraud, Fraunhofer IOSB
+ */
+
+
+/********************/
+/* Client Lifecycle */
+/********************/
+
+static void
+UA_Client_init(UA_Client* client, UA_ClientConfig config) {
+ memset(client, 0, sizeof(UA_Client));
+ /* TODO: Select policy according to the endpoint */
+ UA_SecurityPolicy_None(&client->securityPolicy, NULL, UA_BYTESTRING_NULL, config.logger);
+ client->channel.securityPolicy = &client->securityPolicy;
+ client->channel.securityMode = UA_MESSAGESECURITYMODE_NONE;
+ client->config = config;
+ if(client->config.stateCallback)
+ client->config.stateCallback(client, client->state);
+}
+
+UA_Client *
+UA_Client_new(UA_ClientConfig config) {
+ UA_Client *client = (UA_Client*)UA_malloc(sizeof(UA_Client));
+ if(!client)
+ return NULL;
+ UA_Client_init(client, config);
+ return client;
+}
+
+static void
+UA_Client_deleteMembers(UA_Client* client) {
+ UA_Client_disconnect(client);
+ client->securityPolicy.deleteMembers(&client->securityPolicy);
+ UA_SecureChannel_deleteMembersCleanup(&client->channel);
+ UA_Connection_deleteMembers(&client->connection);
+ if(client->endpointUrl.data)
+ UA_String_deleteMembers(&client->endpointUrl);
+ UA_UserTokenPolicy_deleteMembers(&client->token);
+ UA_NodeId_deleteMembers(&client->authenticationToken);
+ if(client->username.data)
+ UA_String_deleteMembers(&client->username);
+ if(client->password.data)
+ UA_String_deleteMembers(&client->password);
+
+ /* Delete the async service calls */
+ UA_Client_AsyncService_removeAll(client, UA_STATUSCODE_BADSHUTDOWN);
+
+ /* Delete the subscriptions */
+#ifdef UA_ENABLE_SUBSCRIPTIONS
+ UA_Client_Subscriptions_clean(client);
+#endif
+}
+
+void
+UA_Client_reset(UA_Client* client) {
+ UA_Client_deleteMembers(client);
+ UA_Client_init(client, client->config);
+}
+
+void
+UA_Client_delete(UA_Client* client) {
+ UA_Client_deleteMembers(client);
+ UA_free(client);
+}
+
+UA_ClientState
+UA_Client_getState(UA_Client *client) {
+ return client->state;
+}
+
+void *
+UA_Client_getContext(UA_Client *client) {
+ if(!client)
+ return NULL;
+ return client->config.clientContext;
+}
+
+/****************/
+/* Raw Services */
+/****************/
+
+/* For synchronous service calls. Execute async responses with a callback. When
+ * the response with the correct requestId turns up, return it via the
+ * SyncResponseDescription pointer. */
+typedef struct {
+ UA_Client *client;
+ UA_Boolean received;
+ UA_UInt32 requestId;
+ void *response;
+ const UA_DataType *responseType;
+} SyncResponseDescription;
+
+/* For both synchronous and asynchronous service calls */
+static UA_StatusCode
+sendSymmetricServiceRequest(UA_Client *client, const void *request,
+ const UA_DataType *requestType, UA_UInt32 *requestId) {
+ UA_StatusCode retval;
+
+ /* If a message is pending in the chunk don't call UA_Client_manuallyRenewSecureChannel
+ * to prevent incomming message desynchronization */
+ if(!client->connection.pendingMessage) {
+ /* Make sure we have a valid session */
+ retval = UA_Client_manuallyRenewSecureChannel(client);
+ if(retval != UA_STATUSCODE_GOOD)
+ return retval;
+ }
+
+ /* Adjusting the request header. The const attribute is violated, but we
+ * only touch the following members: */
+ UA_RequestHeader *rr = (UA_RequestHeader*)(uintptr_t)request;
+ rr->authenticationToken = client->authenticationToken; /* cleaned up at the end */
+ rr->timestamp = UA_DateTime_now();
+ rr->requestHandle = ++client->requestHandle;
+
+ /* Send the request */
+ UA_UInt32 rqId = ++client->requestId;
+ UA_LOG_DEBUG(client->config.logger, UA_LOGCATEGORY_CLIENT,
+ "Sending a request of type %i", requestType->typeId.identifier.numeric);
+
+ if (client->channel.nextSecurityToken.tokenId != 0) // Change to the new security token if the secure channel has been renewed.
+ UA_SecureChannel_revolveTokens(&client->channel);
+ retval = UA_SecureChannel_sendSymmetricMessage(&client->channel, rqId, UA_MESSAGETYPE_MSG,
+ rr, requestType);
+ UA_NodeId_init(&rr->authenticationToken); /* Do not return the token to the user */
+ if(retval != UA_STATUSCODE_GOOD)
+ return retval;
+
+ *requestId = rqId;
+ return UA_STATUSCODE_GOOD;
+}
+
+static const UA_NodeId
+serviceFaultId = {0, UA_NODEIDTYPE_NUMERIC, {UA_NS0ID_SERVICEFAULT_ENCODING_DEFAULTBINARY}};
+
+/* Look for the async callback in the linked list, execute and delete it */
+static UA_StatusCode
+processAsyncResponse(UA_Client *client, UA_UInt32 requestId, const UA_NodeId *responseTypeId,
+ const UA_ByteString *responseMessage, size_t *offset) {
+ /* Find the callback */
+ AsyncServiceCall *ac;
+ LIST_FOREACH(ac, &client->asyncServiceCalls, pointers) {
+ if(ac->requestId == requestId)
+ break;
+ }
+ if(!ac)
+ return UA_STATUSCODE_BADREQUESTHEADERINVALID;
+
+ /* Allocate the response */
+ UA_STACKARRAY(UA_Byte, responseBuf, ac->responseType->memSize);
+ void *response = (void*)(uintptr_t)&responseBuf[0]; /* workaround aliasing rules */
+
+ /* Verify the type of the 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)) {
+ UA_init(response, ac->responseType);
+ if(UA_NodeId_equal(responseTypeId, &serviceFaultId)) {
+ /* Decode as a ServiceFault, i.e. only the response header */
+ UA_LOG_INFO(client->config.logger, UA_LOGCATEGORY_CLIENT,
+ "Received a ServiceFault response");
+ responseType = &UA_TYPES[UA_TYPES_SERVICEFAULT];
+ } else {
+ /* Close the connection */
+ UA_LOG_ERROR(client->config.logger, UA_LOGCATEGORY_CLIENT,
+ "Reply contains the wrong service response");
+ retval = UA_STATUSCODE_BADCOMMUNICATIONERROR;
+ goto process;
+ }
+ }
+
+ /* Decode the response */
+ retval = UA_decodeBinary(responseMessage, offset, response,
+ responseType, 0, NULL);
+
+ 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));
+ ((UA_ResponseHeader*)response)->serviceResult = retval;
+ }
+
+ /* Call the callback */
+ if (ac->callback)
+ ac->callback(client, ac->userdata, requestId, response, ac->responseType);
+ UA_deleteMembers(response, ac->responseType);
+
+ /* Remove the callback */
+ LIST_REMOVE(ac, pointers);
+ UA_free(ac);
+ return retval;
+}
+
+/* Processes the received service response. Either with an async callback or by
+ * decoding the message and returning it "upwards" in the
+ * SyncResponseDescription. */
+static UA_StatusCode
+processServiceResponse(void *application, UA_SecureChannel *channel,
+ UA_MessageType messageType, UA_UInt32 requestId,
+ const UA_ByteString *message) {
+ SyncResponseDescription *rd = (SyncResponseDescription*)application;
+
+ /* Must be OPN or MSG */
+ if(messageType != UA_MESSAGETYPE_OPN &&
+ messageType != UA_MESSAGETYPE_MSG) {
+ UA_LOG_TRACE_CHANNEL(rd->client->config.logger, channel,
+ "Invalid message type");
+ return UA_STATUSCODE_BADTCPMESSAGETYPEINVALID;
+ }
+
+ /* Has the SecureChannel timed out?
+ * TODO: Solve this for client and server together */
+ if(rd->client->state >= UA_CLIENTSTATE_SECURECHANNEL &&
+ (channel->securityToken.createdAt +
+ (channel->securityToken.revisedLifetime * UA_DATETIME_MSEC))
+ < UA_DateTime_nowMonotonic())
+ return UA_STATUSCODE_BADSECURECHANNELCLOSED;
+
+ /* Decode the data type identifier of the response */
+ size_t offset = 0;
+ UA_NodeId responseId;
+ UA_StatusCode retval = UA_NodeId_decodeBinary(message, &offset, &responseId);
+ if(retval != UA_STATUSCODE_GOOD)
+ goto finish;
+
+ /* Got an asynchronous response. Don't expected a synchronous response
+ * (responseType NULL) or the id does not match. */
+ if(!rd->responseType || requestId != rd->requestId) {
+ retval = processAsyncResponse(rd->client, requestId, &responseId, message, &offset);
+ goto finish;
+ }
+
+ /* Got the synchronous response */
+ rd->received = true;
+
+ /* Forward declaration for the goto */
+ UA_NodeId expectedNodeId = UA_NODEID_NUMERIC(0, rd->responseType->binaryEncodingId);
+
+ /* Check that the response type matches */
+ if(!UA_NodeId_equal(&responseId, &expectedNodeId)) {
+ if(UA_NodeId_equal(&responseId, &serviceFaultId)) {
+ UA_LOG_INFO(rd->client->config.logger, UA_LOGCATEGORY_CLIENT,
+ "Received a ServiceFault response");
+ UA_init(rd->response, rd->responseType);
+ retval = UA_decodeBinary(message, &offset, rd->response,
+ &UA_TYPES[UA_TYPES_SERVICEFAULT], 0, NULL);
+ } else {
+ /* Close the connection */
+ UA_LOG_ERROR(rd->client->config.logger, UA_LOGCATEGORY_CLIENT,
+ "Reply contains the wrong service response");
+ retval = UA_STATUSCODE_BADCOMMUNICATIONERROR;
+ }
+ goto finish;
+ }
+
+ UA_LOG_DEBUG(rd->client->config.logger, UA_LOGCATEGORY_CLIENT,
+ "Decode a message of type %u", responseId.identifier.numeric);
+
+ /* Decode the response */
+ retval = UA_decodeBinary(message, &offset, rd->response, rd->responseType,
+ rd->client->config.customDataTypesSize,
+ rd->client->config.customDataTypes);
+
+finish:
+ UA_NodeId_deleteMembers(&responseId);
+ if(retval != UA_STATUSCODE_GOOD) {
+ if(retval == UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED)
+ retval = UA_STATUSCODE_BADRESPONSETOOLARGE;
+ UA_LOG_INFO(rd->client->config.logger, UA_LOGCATEGORY_CLIENT,
+ "Error receiving the response with status code %s",
+ UA_StatusCode_name(retval));
+
+ if(rd->response) {
+ UA_ResponseHeader *respHeader = (UA_ResponseHeader*)rd->response;
+ respHeader->serviceResult = retval;
+ }
+ }
+ return retval;
+}
+
+/* Forward complete chunks directly to the securechannel */
+static UA_StatusCode
+client_processChunk(void *application, UA_Connection *connection, UA_ByteString *chunk) {
+ SyncResponseDescription *rd = (SyncResponseDescription*)application;
+ return UA_SecureChannel_processChunk(&rd->client->channel, chunk,
+ processServiceResponse,
+ rd, UA_TRUE);
+}
+
+/* Receive and process messages until a synchronous message arrives or the
+ * timout finishes */
+UA_StatusCode
+receiveServiceResponse(UA_Client *client, void *response, const UA_DataType *responseType,
+ UA_DateTime maxDate, UA_UInt32 *synchronousRequestId) {
+ /* Prepare the response and the structure we give into processServiceResponse */
+ SyncResponseDescription rd = { client, false, 0, response, responseType };
+
+ /* Return upon receiving the synchronized response. All other responses are
+ * processed with a callback "in the background". */
+ if(synchronousRequestId)
+ rd.requestId = *synchronousRequestId;
+
+ UA_StatusCode retval;
+ do {
+ UA_DateTime now = UA_DateTime_nowMonotonic();
+
+ /* >= avoid timeout to be set to 0 */
+ if(now >= maxDate)
+ return UA_STATUSCODE_GOODNONCRITICALTIMEOUT;
+
+ /* round always to upper value to avoid timeout to be set to 0
+ * if(maxDate - now) < (UA_DATETIME_MSEC/2) */
+ UA_UInt32 timeout = (UA_UInt32)(((maxDate - now) + (UA_DATETIME_MSEC - 1)) / UA_DATETIME_MSEC);
+
+ retval = UA_Connection_receiveChunksBlocking(&client->connection, &rd, client_processChunk, timeout);
+
+ if(retval != UA_STATUSCODE_GOOD && retval != UA_STATUSCODE_GOODNONCRITICALTIMEOUT) {
+ if(retval == UA_STATUSCODE_BADCONNECTIONCLOSED)
+ setClientState(client, UA_CLIENTSTATE_DISCONNECTED);
+ UA_Client_close(client);
+ break;
+ }
+ } while(!rd.received);
+ return retval;
+}
+
+void
+__UA_Client_Service(UA_Client *client, const void *request,
+ const UA_DataType *requestType, void *response,
+ const UA_DataType *responseType) {
+ UA_init(response, responseType);
+ UA_ResponseHeader *respHeader = (UA_ResponseHeader*)response;
+
+ /* Send the request */
+ UA_UInt32 requestId;
+ UA_StatusCode retval = sendSymmetricServiceRequest(client, request, requestType, &requestId);
+ if(retval != UA_STATUSCODE_GOOD) {
+ if(retval == UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED)
+ respHeader->serviceResult = UA_STATUSCODE_BADREQUESTTOOLARGE;
+ else
+ respHeader->serviceResult = retval;
+ UA_Client_close(client);
+ return;
+ }
+
+ /* Retrieve the response */
+ UA_DateTime maxDate = UA_DateTime_nowMonotonic() +
+ (client->config.timeout * UA_DATETIME_MSEC);
+ retval = receiveServiceResponse(client, response, responseType, maxDate, &requestId);
+ if(retval == UA_STATUSCODE_GOODNONCRITICALTIMEOUT) {
+ /* In synchronous service, if we have don't have a reply we need to close the connection */
+ UA_Client_close(client);
+ retval = UA_STATUSCODE_BADCONNECTIONCLOSED;
+ }
+ if(retval != UA_STATUSCODE_GOOD)
+ respHeader->serviceResult = retval;
+}
+
+void
+UA_Client_AsyncService_cancel(UA_Client *client, AsyncServiceCall *ac,
+ UA_StatusCode statusCode) {
+ /* Create an empty response with the statuscode */
+ UA_STACKARRAY(UA_Byte, responseBuf, ac->responseType->memSize);
+ void *resp = (void*)(uintptr_t)&responseBuf[0]; /* workaround aliasing rules */
+ UA_init(resp, ac->responseType);
+ ((UA_ResponseHeader*)resp)->serviceResult = statusCode;
+
+ if (ac->callback)
+ ac->callback(client, ac->userdata, ac->requestId, resp, ac->responseType);
+
+ /* Clean up the response. Users might move data into it. For whatever reasons. */
+ UA_deleteMembers(resp, ac->responseType);
+}
+
+void UA_Client_AsyncService_removeAll(UA_Client *client, UA_StatusCode statusCode) {
+ AsyncServiceCall *ac, *ac_tmp;
+ LIST_FOREACH_SAFE(ac, &client->asyncServiceCalls, pointers, ac_tmp) {
+ LIST_REMOVE(ac, pointers);
+ UA_Client_AsyncService_cancel(client, ac, statusCode);
+ UA_free(ac);
+ }
+}
+
+UA_StatusCode
+__UA_Client_AsyncServiceEx(UA_Client *client, const void *request,
+ const UA_DataType *requestType,
+ UA_ClientAsyncServiceCallback callback,
+ const UA_DataType *responseType,
+ void *userdata, UA_UInt32 *requestId,
+ UA_UInt32 timeout) {
+ /* Prepare the entry for the linked list */
+ AsyncServiceCall *ac = (AsyncServiceCall*)UA_malloc(sizeof(AsyncServiceCall));
+ if(!ac)
+ return UA_STATUSCODE_BADOUTOFMEMORY;
+ ac->callback = callback;
+ ac->responseType = responseType;
+ ac->userdata = userdata;
+ ac->timeout = timeout;
+
+ /* Call the service and set the requestId */
+ UA_StatusCode retval = sendSymmetricServiceRequest(client, request, requestType, &ac->requestId);
+ if(retval != UA_STATUSCODE_GOOD) {
+ ac->requestId = 0;
+ UA_Client_AsyncService_cancel(client, ac, UA_STATUSCODE_BADTIMEOUT);
+ UA_free(ac);
+ return retval;
+ }
+
+ ac->start = UA_DateTime_nowMonotonic();
+
+ /* Store the entry for async processing */
+ LIST_INSERT_HEAD(&client->asyncServiceCalls, ac, pointers);
+ if(requestId)
+ *requestId = ac->requestId;
+ return UA_STATUSCODE_GOOD;
+}
+
+UA_StatusCode
+__UA_Client_AsyncService(UA_Client *client, const void *request,
+ const UA_DataType *requestType,
+ UA_ClientAsyncServiceCallback callback,
+ const UA_DataType *responseType,
+ void *userdata, UA_UInt32 *requestId) {
+ return __UA_Client_AsyncServiceEx(client, request, requestType, callback,
+ responseType, userdata, requestId,
+ client->config.timeout);
+}
+
+static void
+backgroundConnectivityCallback(UA_Client *client, void *userdata,
+ UA_UInt32 requestId, const UA_ReadResponse *response,
+ const UA_DataType *responseType) {
+ if(response->responseHeader.serviceResult == UA_STATUSCODE_BADTIMEOUT) {
+ if (client->config.inactivityCallback)
+ client->config.inactivityCallback(client);
+ }
+ client->pendingConnectivityCheck = false;
+ client->lastConnectivityCheck = UA_DateTime_nowMonotonic();
+}
+
+static UA_StatusCode
+UA_Client_backgroundConnectivity(UA_Client *client) {
+ if(!client->config.connectivityCheckInterval)
+ return UA_STATUSCODE_GOOD;
+
+ if (client->pendingConnectivityCheck)
+ return UA_STATUSCODE_GOOD;
+
+ UA_DateTime now = UA_DateTime_nowMonotonic();
+ UA_DateTime nextDate = client->lastConnectivityCheck + (UA_DateTime)(client->config.connectivityCheckInterval * UA_DATETIME_MSEC);
+
+ if(now <= nextDate)
+ return UA_STATUSCODE_GOOD;
+
+ UA_ReadRequest request;
+ UA_ReadRequest_init(&request);
+
+ UA_ReadValueId rvid;
+ UA_ReadValueId_init(&rvid);
+ rvid.attributeId = UA_ATTRIBUTEID_VALUE;
+ rvid.nodeId = UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERSTATUS_STATE);
+
+ request.nodesToRead = &rvid;
+ request.nodesToReadSize = 1;
+
+ UA_StatusCode retval = __UA_Client_AsyncService(client, &request, &UA_TYPES[UA_TYPES_READREQUEST],
+ (UA_ClientAsyncServiceCallback)backgroundConnectivityCallback,
+ &UA_TYPES[UA_TYPES_READRESPONSE], NULL, NULL);
+
+ client->pendingConnectivityCheck = true;
+
+ return retval;
+}
+
+static void
+asyncServiceTimeoutCheck(UA_Client *client) {
+ UA_DateTime now = UA_DateTime_nowMonotonic();
+
+ /* Timeout occurs, remove the callback */
+ AsyncServiceCall *ac, *ac_tmp;
+ LIST_FOREACH_SAFE(ac, &client->asyncServiceCalls, pointers, ac_tmp) {
+ if (!ac->timeout)
+ continue;
+
+ if (ac->start + (UA_DateTime)(ac->timeout * UA_DATETIME_MSEC) <= now) {
+ LIST_REMOVE(ac, pointers);
+ UA_Client_AsyncService_cancel(client, ac, UA_STATUSCODE_BADTIMEOUT);
+ UA_free(ac);
+ }
+ }
+}
+
+UA_StatusCode
+UA_Client_runAsync(UA_Client *client, UA_UInt16 timeout) {
+ /* TODO: Call repeated jobs that are scheduled */
+#ifdef UA_ENABLE_SUBSCRIPTIONS
+ UA_StatusCode retvalPublish = UA_Client_Subscriptions_backgroundPublish(client);
+ if (retvalPublish != UA_STATUSCODE_GOOD)
+ return retvalPublish;
+#endif
+ UA_StatusCode retval = UA_Client_manuallyRenewSecureChannel(client);
+ if (retval != UA_STATUSCODE_GOOD)
+ return retval;
+
+ retval = UA_Client_backgroundConnectivity(client);
+ if(retval != UA_STATUSCODE_GOOD)
+ return retval;
+
+ UA_DateTime maxDate = UA_DateTime_nowMonotonic() + (timeout * UA_DATETIME_MSEC);
+ retval = receiveServiceResponse(client, NULL, NULL, maxDate, NULL);
+ if(retval == UA_STATUSCODE_GOODNONCRITICALTIMEOUT)
+ retval = UA_STATUSCODE_GOOD;
+#ifdef UA_ENABLE_SUBSCRIPTIONS
+ /* The inactivity check must be done after receiveServiceResponse */
+ UA_Client_Subscriptions_backgroundPublishInactivityCheck(client);
+#endif
+ asyncServiceTimeoutCheck(client);
+ return retval;
+}
+
+/*********************************** amalgamated original file "/home/jvoe/open62541/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
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * Copyright 2017 (c) Mark Giraud, Fraunhofer IOSB
+ * Copyright 2017-2018 (c) Thomas Stalder, Blue Time Concept SA
+ * Copyright 2017 (c) Julius Pfrommer, Fraunhofer IOSB
+ * Copyright 2017 (c) Stefan Profanter, fortiss GmbH
+ */
+
+
+#define UA_MINMESSAGESIZE 8192
+
+
+ /********************/
+ /* Set client state */
+ /********************/
+void
+setClientState(UA_Client *client, UA_ClientState state) {
+ if(client->state != state) {
+ client->state = state;
+ if(client->config.stateCallback)
+ client->config.stateCallback(client, client->state);
+ }
+}
+
+/***********************/
+/* Open the Connection */
+/***********************/
+
+#define UA_BITMASK_MESSAGETYPE 0x00ffffff
+#define UA_BITMASK_CHUNKTYPE 0xff000000
+
+static UA_StatusCode
+processACKResponse(void *application, UA_Connection *connection, UA_ByteString *chunk) {
+ UA_Client *client = (UA_Client*)application;
+
+ /* Decode the message */
+ size_t offset = 0;
+ UA_StatusCode retval;
+ UA_TcpMessageHeader messageHeader;
+ UA_TcpAcknowledgeMessage ackMessage;
+ retval = UA_TcpMessageHeader_decodeBinary(chunk, &offset, &messageHeader);
+ if(retval != UA_STATUSCODE_GOOD) {
+ UA_LOG_INFO(client->config.logger, UA_LOGCATEGORY_NETWORK,
+ "Decoding ACK message failed");
+ return retval;
+ }
+
+ // check if we got an error response from the server
+ UA_MessageType messageType = (UA_MessageType)
+ (messageHeader.messageTypeAndChunkType & UA_BITMASK_MESSAGETYPE);
+ UA_ChunkType chunkType = (UA_ChunkType)
+ (messageHeader.messageTypeAndChunkType & UA_BITMASK_CHUNKTYPE);
+ if (messageType == UA_MESSAGETYPE_ERR) {
+ // Header + ErrorMessage (error + reasonLength_field + length)
+ UA_StatusCode error = *(UA_StatusCode*)(&chunk->data[offset]);
+ UA_UInt32 len = *((UA_UInt32*)&chunk->data[offset + 4]);
+ UA_Byte *data = (UA_Byte*)&chunk->data[offset + 4+4];
+ UA_LOG_ERROR(client->config.logger, UA_LOGCATEGORY_NETWORK,
+ "Received ERR response. %s - %.*s", UA_StatusCode_name(error), len, data);
+ return UA_STATUSCODE_BADTCPMESSAGETYPEINVALID;
+ }
+ if (chunkType != UA_CHUNKTYPE_FINAL) {
+ return UA_STATUSCODE_BADTCPMESSAGETYPEINVALID;
+ }
+
+ retval |= UA_TcpAcknowledgeMessage_decodeBinary(chunk, &offset, &ackMessage);
+ if(retval != UA_STATUSCODE_GOOD) {
+ UA_LOG_INFO(client->config.logger, UA_LOGCATEGORY_NETWORK,
+ "Decoding ACK message failed");
+ return retval;
+ }
+
+ /* Store remote connection settings and adjust local configuration to not
+ * exceed the limits */
+ UA_LOG_DEBUG(client->config.logger, UA_LOGCATEGORY_NETWORK, "Received ACK message");
+ connection->remoteConf.maxChunkCount = ackMessage.maxChunkCount; /* may be zero -> unlimited */
+ connection->remoteConf.maxMessageSize = ackMessage.maxMessageSize; /* may be zero -> unlimited */
+ connection->remoteConf.protocolVersion = ackMessage.protocolVersion;
+ connection->remoteConf.sendBufferSize = ackMessage.sendBufferSize;
+ connection->remoteConf.recvBufferSize = ackMessage.receiveBufferSize;
+ if(connection->remoteConf.recvBufferSize < connection->localConf.sendBufferSize)
+ connection->localConf.sendBufferSize = connection->remoteConf.recvBufferSize;
+ if(connection->remoteConf.sendBufferSize < connection->localConf.recvBufferSize)
+ connection->localConf.recvBufferSize = connection->remoteConf.sendBufferSize;
+ connection->state = UA_CONNECTION_ESTABLISHED;
+ return UA_STATUSCODE_GOOD;
+}
+
+static UA_StatusCode
+HelAckHandshake(UA_Client *client) {
+ /* Get a buffer */
+ UA_ByteString message;
+ UA_Connection *conn = &client->connection;
+ UA_StatusCode retval = conn->getSendBuffer(conn, UA_MINMESSAGESIZE, &message);
+ if(retval != UA_STATUSCODE_GOOD)
+ return retval;
+
+ /* Prepare the HEL message and encode at offset 8 */
+ UA_TcpHelloMessage hello;
+ UA_String_copy(&client->endpointUrl, &hello.endpointUrl); /* must be less than 4096 bytes */
+ hello.maxChunkCount = conn->localConf.maxChunkCount;
+ hello.maxMessageSize = conn->localConf.maxMessageSize;
+ hello.protocolVersion = conn->localConf.protocolVersion;
+ hello.receiveBufferSize = conn->localConf.recvBufferSize;
+ hello.sendBufferSize = conn->localConf.sendBufferSize;
+
+ UA_Byte *bufPos = &message.data[8]; /* skip the header */
+ const UA_Byte *bufEnd = &message.data[message.length];
+ retval = UA_TcpHelloMessage_encodeBinary(&hello, &bufPos, &bufEnd);
+ UA_TcpHelloMessage_deleteMembers(&hello);
+
+ /* 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);
+ if(retval != UA_STATUSCODE_GOOD) {
+ conn->releaseSendBuffer(conn, &message);
+ return retval;
+ }
+
+ /* Send the HEL message */
+ message.length = messageHeader.messageSize;
+ retval = conn->send(conn, &message);
+ if(retval != UA_STATUSCODE_GOOD) {
+ UA_LOG_INFO(client->config.logger, UA_LOGCATEGORY_NETWORK,
+ "Sending HEL failed");
+ return retval;
+ }
+ UA_LOG_DEBUG(client->config.logger, UA_LOGCATEGORY_NETWORK,
+ "Sent HEL message");
+
+ /* Loop until we have a complete chunk */
+ retval = UA_Connection_receiveChunksBlocking(conn, client, processACKResponse,
+ client->config.timeout);
+ if(retval != UA_STATUSCODE_GOOD) {
+ UA_LOG_INFO(client->config.logger, UA_LOGCATEGORY_NETWORK,
+ "Receiving ACK message failed");
+ if(retval == UA_STATUSCODE_BADCONNECTIONCLOSED)
+ client->state = UA_CLIENTSTATE_DISCONNECTED;
+ UA_Client_close(client);
+ }
+ return retval;
+}
+
+static void
+processDecodedOPNResponse(UA_Client *client, UA_OpenSecureChannelResponse *response, UA_Boolean renew) {
+ /* Replace the token */
+ if (renew)
+ client->channel.nextSecurityToken = response->securityToken; // Set the next token
+ else
+ client->channel.securityToken = response->securityToken; // Set initial token
+
+ /* Replace the nonce */
+ UA_ByteString_deleteMembers(&client->channel.remoteNonce);
+ client->channel.remoteNonce = response->serverNonce;
+ UA_ByteString_init(&response->serverNonce);
+
+ if(client->channel.state == UA_SECURECHANNELSTATE_OPEN)
+ UA_LOG_DEBUG(client->config.logger, UA_LOGCATEGORY_SECURECHANNEL,
+ "SecureChannel in the server renewed");
+ else
+ UA_LOG_DEBUG(client->config.logger, UA_LOGCATEGORY_SECURECHANNEL,
+ "Opened SecureChannel acknowledged by the server");
+
+ /* Response.securityToken.revisedLifetime is UInt32 we need to cast it to
+ * DateTime=Int64 we take 75% of lifetime to start renewing as described in
+ * standard */
+ client->channel.state = UA_SECURECHANNELSTATE_OPEN;
+ client->nextChannelRenewal = UA_DateTime_nowMonotonic() + (UA_DateTime)
+ (client->channel.securityToken.revisedLifetime * (UA_Double)UA_DATETIME_MSEC * 0.75);
+}
+
+static UA_StatusCode
+openSecureChannel(UA_Client *client, UA_Boolean renew) {
+ /* Check if sc is still valid */
+ if(renew && client->nextChannelRenewal > UA_DateTime_nowMonotonic())
+ return UA_STATUSCODE_GOOD;
+
+ UA_Connection *conn = &client->connection;
+ if(conn->state != UA_CONNECTION_ESTABLISHED)
+ return UA_STATUSCODE_BADSERVERNOTCONNECTED;
+
+ /* Prepare the OpenSecureChannelRequest */
+ UA_OpenSecureChannelRequest opnSecRq;
+ UA_OpenSecureChannelRequest_init(&opnSecRq);
+ opnSecRq.requestHeader.timestamp = UA_DateTime_now();
+ opnSecRq.requestHeader.authenticationToken = client->authenticationToken;
+ if(renew) {
+ opnSecRq.requestType = UA_SECURITYTOKENREQUESTTYPE_RENEW;
+ UA_LOG_DEBUG(client->config.logger, UA_LOGCATEGORY_SECURECHANNEL,
+ "Requesting to renew the SecureChannel");
+ } else {
+ opnSecRq.requestType = UA_SECURITYTOKENREQUESTTYPE_ISSUE;
+ UA_LOG_DEBUG(client->config.logger, UA_LOGCATEGORY_SECURECHANNEL,
+ "Requesting to open a SecureChannel");
+ }
+ opnSecRq.securityMode = UA_MESSAGESECURITYMODE_NONE;
+ opnSecRq.clientNonce = client->channel.localNonce;
+ opnSecRq.requestedLifetime = client->config.secureChannelLifeTime;
+
+ /* Send the OPN message */
+ UA_UInt32 requestId = ++client->requestId;
+ UA_StatusCode retval =
+ UA_SecureChannel_sendAsymmetricOPNMessage(&client->channel, requestId, &opnSecRq,
+ &UA_TYPES[UA_TYPES_OPENSECURECHANNELREQUEST]);
+ if(retval != UA_STATUSCODE_GOOD) {
+ UA_LOG_ERROR(client->config.logger, UA_LOGCATEGORY_SECURECHANNEL,
+ "Sending OPN message failed with error %s", UA_StatusCode_name(retval));
+ UA_Client_close(client);
+ return retval;
+ }
+
+ UA_LOG_DEBUG(client->config.logger, UA_LOGCATEGORY_SECURECHANNEL, "OPN message sent");
+
+ /* Increase nextChannelRenewal to avoid that we re-start renewal when
+ * publish responses are received before the OPN response arrives. */
+ client->nextChannelRenewal = UA_DateTime_nowMonotonic() +
+ (2 * ((UA_DateTime)client->config.timeout * UA_DATETIME_MSEC));
+
+ /* Receive / decrypt / decode the OPN response. Process async services in
+ * the background until the OPN response arrives. */
+ UA_OpenSecureChannelResponse response;
+ retval = receiveServiceResponse(client, &response,
+ &UA_TYPES[UA_TYPES_OPENSECURECHANNELRESPONSE],
+ UA_DateTime_nowMonotonic() +
+ ((UA_DateTime)client->config.timeout * UA_DATETIME_MSEC),
+ &requestId);
+
+ if(retval != UA_STATUSCODE_GOOD) {
+ UA_Client_close(client);
+ return retval;
+ }
+
+ processDecodedOPNResponse(client, &response, renew);
+ UA_OpenSecureChannelResponse_deleteMembers(&response);
+ return retval;
+}
+
+static UA_StatusCode
+activateSession(UA_Client *client) {
+ UA_ActivateSessionRequest request;
+ UA_ActivateSessionRequest_init(&request);
+ request.requestHeader.requestHandle = ++client->requestHandle;
+ request.requestHeader.timestamp = UA_DateTime_now();
+ request.requestHeader.timeoutHint = 600000;
+
+ //manual ExtensionObject encoding of the identityToken
+ if(client->authenticationMethod == UA_CLIENTAUTHENTICATION_NONE) {
+ UA_AnonymousIdentityToken* identityToken = UA_AnonymousIdentityToken_new();
+ UA_AnonymousIdentityToken_init(identityToken);
+ UA_String_copy(&client->token.policyId, &identityToken->policyId);
+ request.userIdentityToken.encoding = UA_EXTENSIONOBJECT_DECODED;
+ request.userIdentityToken.content.decoded.type = &UA_TYPES[UA_TYPES_ANONYMOUSIDENTITYTOKEN];
+ request.userIdentityToken.content.decoded.data = identityToken;
+ } else {
+ UA_UserNameIdentityToken* identityToken = UA_UserNameIdentityToken_new();
+ UA_UserNameIdentityToken_init(identityToken);
+ UA_String_copy(&client->token.policyId, &identityToken->policyId);
+ UA_String_copy(&client->username, &identityToken->userName);
+ UA_String_copy(&client->password, &identityToken->password);
+ request.userIdentityToken.encoding = UA_EXTENSIONOBJECT_DECODED;
+ request.userIdentityToken.content.decoded.type = &UA_TYPES[UA_TYPES_USERNAMEIDENTITYTOKEN];
+ request.userIdentityToken.content.decoded.data = identityToken;
+ }
+
+ UA_ActivateSessionResponse response;
+ __UA_Client_Service(client, &request, &UA_TYPES[UA_TYPES_ACTIVATESESSIONREQUEST],
+ &response, &UA_TYPES[UA_TYPES_ACTIVATESESSIONRESPONSE]);
+
+ if(response.responseHeader.serviceResult != UA_STATUSCODE_GOOD) {
+ UA_LOG_ERROR(client->config.logger, UA_LOGCATEGORY_CLIENT,
+ "ActivateSession failed with error code %s",
+ UA_StatusCode_name(response.responseHeader.serviceResult));
+ }
+
+ UA_StatusCode retval = response.responseHeader.serviceResult;
+ UA_ActivateSessionRequest_deleteMembers(&request);
+ UA_ActivateSessionResponse_deleteMembers(&response);
+ return retval;
+}
+
+/* Gets a list of endpoints. Memory is allocated for endpointDescription array */
+UA_StatusCode
+UA_Client_getEndpointsInternal(UA_Client *client, size_t* endpointDescriptionsSize,
+ UA_EndpointDescription** endpointDescriptions) {
+ UA_GetEndpointsRequest request;
+ UA_GetEndpointsRequest_init(&request);
+ request.requestHeader.timestamp = UA_DateTime_now();
+ request.requestHeader.timeoutHint = 10000;
+ // assume the endpointurl outlives the service call
+ request.endpointUrl = client->endpointUrl;
+
+ UA_GetEndpointsResponse response;
+ __UA_Client_Service(client, &request, &UA_TYPES[UA_TYPES_GETENDPOINTSREQUEST],
+ &response, &UA_TYPES[UA_TYPES_GETENDPOINTSRESPONSE]);
+
+ if(response.responseHeader.serviceResult != UA_STATUSCODE_GOOD) {
+ UA_StatusCode retval = response.responseHeader.serviceResult;
+ UA_LOG_ERROR(client->config.logger, UA_LOGCATEGORY_CLIENT,
+ "GetEndpointRequest failed with error code %s",
+ UA_StatusCode_name(retval));
+ UA_GetEndpointsResponse_deleteMembers(&response);
+ return retval;
+ }
+ *endpointDescriptions = response.endpoints;
+ *endpointDescriptionsSize = response.endpointsSize;
+ response.endpoints = NULL;
+ response.endpointsSize = 0;
+ UA_GetEndpointsResponse_deleteMembers(&response);
+ return UA_STATUSCODE_GOOD;
+}
+
+static UA_StatusCode
+getEndpoints(UA_Client *client) {
+ UA_EndpointDescription* endpointArray = NULL;
+ size_t endpointArraySize = 0;
+ UA_StatusCode retval =
+ UA_Client_getEndpointsInternal(client, &endpointArraySize, &endpointArray);
+ if(retval != UA_STATUSCODE_GOOD)
+ return retval;
+
+ UA_Boolean endpointFound = false;
+ UA_Boolean tokenFound = false;
+ UA_String securityNone = UA_STRING("http://opcfoundation.org/UA/SecurityPolicy#None");
+ UA_String binaryTransport = UA_STRING("http://opcfoundation.org/UA-Profile/"
+ "Transport/uatcp-uasc-uabinary");
+
+ // TODO: compare endpoint information with client->endpointUri
+ for(size_t i = 0; i < endpointArraySize; ++i) {
+ UA_EndpointDescription* endpoint = &endpointArray[i];
+ /* look out for binary transport endpoints */
+ /* Note: Siemens returns empty ProfileUrl, we will accept it as binary */
+ if(endpoint->transportProfileUri.length != 0 &&
+ !UA_String_equal(&endpoint->transportProfileUri, &binaryTransport))
+ continue;
+ /* look out for an endpoint without security */
+ if(!UA_String_equal(&endpoint->securityPolicyUri, &securityNone))
+ continue;
+
+ /* endpoint with no security found */
+ endpointFound = true;
+
+ /* look for a user token policy with an anonymous token */
+ for(size_t j = 0; j < endpoint->userIdentityTokensSize; ++j) {
+ UA_UserTokenPolicy* userToken = &endpoint->userIdentityTokens[j];
+
+ /* Usertokens also have a security policy... */
+ if(userToken->securityPolicyUri.length > 0 &&
+ !UA_String_equal(&userToken->securityPolicyUri, &securityNone))
+ continue;
+
+ /* UA_CLIENTAUTHENTICATION_NONE == UA_USERTOKENTYPE_ANONYMOUS
+ * UA_CLIENTAUTHENTICATION_USERNAME == UA_USERTOKENTYPE_USERNAME
+ * TODO: Check equivalence for other types when adding the support */
+ if((int)client->authenticationMethod != (int)userToken->tokenType)
+ continue;
+
+ /* Endpoint with matching usertokenpolicy found */
+ tokenFound = true;
+ UA_UserTokenPolicy_deleteMembers(&client->token);
+ UA_UserTokenPolicy_copy(userToken, &client->token);
+ break;
+ }
+ }
+
+ UA_Array_delete(endpointArray, endpointArraySize,
+ &UA_TYPES[UA_TYPES_ENDPOINTDESCRIPTION]);
+
+ if(!endpointFound) {
+ UA_LOG_ERROR(client->config.logger, UA_LOGCATEGORY_CLIENT,
+ "No suitable endpoint found");
+ retval = UA_STATUSCODE_BADINTERNALERROR;
+ } else if(!tokenFound) {
+ UA_LOG_ERROR(client->config.logger, UA_LOGCATEGORY_CLIENT,
+ "No suitable UserTokenPolicy found for the possible endpoints");
+ retval = UA_STATUSCODE_BADINTERNALERROR;
+ }
+ return retval;
+}
+
+static UA_StatusCode
+createSession(UA_Client *client) {
+ UA_CreateSessionRequest request;
+ UA_CreateSessionRequest_init(&request);
+
+ request.requestHeader.timestamp = UA_DateTime_now();
+ request.requestHeader.timeoutHint = 10000;
+ UA_ByteString_copy(&client->channel.localNonce, &request.clientNonce);
+ request.requestedSessionTimeout = 1200000;
+ request.maxResponseMessageSize = UA_INT32_MAX;
+ UA_String_copy(&client->endpointUrl, &request.endpointUrl);
+
+ UA_CreateSessionResponse response;
+ __UA_Client_Service(client, &request, &UA_TYPES[UA_TYPES_CREATESESSIONREQUEST],
+ &response, &UA_TYPES[UA_TYPES_CREATESESSIONRESPONSE]);
+
+ UA_NodeId_copy(&response.authenticationToken, &client->authenticationToken);
+
+ UA_StatusCode retval = response.responseHeader.serviceResult;
+ UA_CreateSessionRequest_deleteMembers(&request);
+ UA_CreateSessionResponse_deleteMembers(&response);
+ return retval;
+}
+
+UA_StatusCode
+UA_Client_connectInternal(UA_Client *client, const char *endpointUrl,
+ UA_Boolean endpointsHandshake, UA_Boolean createNewSession) {
+ if(client->state >= UA_CLIENTSTATE_CONNECTED)
+ return UA_STATUSCODE_GOOD;
+ UA_ChannelSecurityToken_init(&client->channel.securityToken);
+ client->channel.state = UA_SECURECHANNELSTATE_FRESH;
+ client->channel.sendSequenceNumber = 0;
+ client->requestId = 0;
+
+ UA_StatusCode retval = UA_STATUSCODE_GOOD;
+ client->connection =
+ client->config.connectionFunc(client->config.localConnectionConfig,
+ endpointUrl, client->config.timeout,
+ client->config.logger);
+ if(client->connection.state != UA_CONNECTION_OPENING) {
+ retval = UA_STATUSCODE_BADCONNECTIONCLOSED;
+ goto cleanup;
+ }
+
+ UA_String_deleteMembers(&client->endpointUrl);
+ client->endpointUrl = UA_STRING_ALLOC(endpointUrl);
+ if(!client->endpointUrl.data) {
+ retval = UA_STATUSCODE_BADOUTOFMEMORY;
+ goto cleanup;
+ }
+
+ /* Open a TCP connection */
+ client->connection.localConf = client->config.localConnectionConfig;
+ retval = HelAckHandshake(client);
+ if(retval != UA_STATUSCODE_GOOD)
+ goto cleanup;
+ setClientState(client, UA_CLIENTSTATE_CONNECTED);
+
+ /* Open a SecureChannel. TODO: Select with endpoint */
+ client->channel.connection = &client->connection;
+ retval = openSecureChannel(client, false);
+ if(retval != UA_STATUSCODE_GOOD)
+ goto cleanup;
+ setClientState(client, UA_CLIENTSTATE_SECURECHANNEL);
+
+
+ /* Delete async service. TODO: Move this from connect to the disconnect/cleanup phase */
+ UA_Client_AsyncService_removeAll(client, UA_STATUSCODE_BADSHUTDOWN);
+
+#ifdef UA_ENABLE_SUBSCRIPTIONS
+ client->currentlyOutStandingPublishRequests = 0;
+#endif
+
+// TODO: actually, reactivate an existing session is working, but currently republish is not implemented
+// This option is disabled until we have a good implementation of the subscription recovery.
+
+#ifdef UA_SESSION_RECOVERY
+ /* Try to activate an existing Session for this SecureChannel */
+ if((!UA_NodeId_equal(&client->authenticationToken, &UA_NODEID_NULL)) && (createNewSession)) {
+ retval = activateSession(client);
+ if(retval == UA_STATUSCODE_BADSESSIONIDINVALID) {
+ /* Could not recover an old session. Remove authenticationToken */
+ UA_NodeId_deleteMembers(&client->authenticationToken);
+ } else {
+ if(retval != UA_STATUSCODE_GOOD)
+ goto cleanup;
+ setClientState(client, UA_CLIENTSTATE_SESSION_RENEWED);
+ return retval;
+ }
+ } else {
+ UA_NodeId_deleteMembers(&client->authenticationToken);
+ }
+#else
+ UA_NodeId_deleteMembers(&client->authenticationToken);
+#endif /* UA_SESSION_RECOVERY */
+
+ /* Get Endpoints */
+ if(endpointsHandshake) {
+ retval = getEndpoints(client);
+ if(retval != UA_STATUSCODE_GOOD)
+ goto cleanup;
+ }
+
+ /* Create the Session for this SecureChannel */
+ if(createNewSession) {
+ retval = createSession(client);
+ if(retval != UA_STATUSCODE_GOOD)
+ goto cleanup;
+#ifdef UA_ENABLE_SUBSCRIPTIONS
+ /* A new session has been created. We need to clean up the subscriptions */
+ UA_Client_Subscriptions_clean(client);
+#endif
+ retval = activateSession(client);
+ if(retval != UA_STATUSCODE_GOOD)
+ goto cleanup;
+ setClientState(client, UA_CLIENTSTATE_SESSION);
+ }
+
+ return retval;
+
+cleanup:
+ UA_Client_close(client);
+ return retval;
+}
+
+UA_StatusCode
+UA_Client_connect(UA_Client *client, const char *endpointUrl) {
+ return UA_Client_connectInternal(client, endpointUrl, UA_TRUE, UA_TRUE);
+}
+
+UA_StatusCode
+UA_Client_connect_username(UA_Client *client, const char *endpointUrl,
+ const char *username, const char *password) {
+ client->authenticationMethod = UA_CLIENTAUTHENTICATION_USERNAME;
+ client->username = UA_STRING_ALLOC(username);
+ client->password = UA_STRING_ALLOC(password);
+ return UA_Client_connect(client, endpointUrl);
+}
+
+UA_StatusCode
+UA_Client_manuallyRenewSecureChannel(UA_Client *client) {
+ UA_StatusCode retval = openSecureChannel(client, true);
+ if(retval != UA_STATUSCODE_GOOD)
+ UA_Client_close(client);
+
+ return retval;
+}
+
+/************************/
+/* Close the Connection */
+/************************/
+
+static void
+sendCloseSession(UA_Client *client) {
+ UA_CloseSessionRequest request;
+ UA_CloseSessionRequest_init(&request);
+
+ request.requestHeader.timestamp = UA_DateTime_now();
+ request.requestHeader.timeoutHint = 10000;
+ request.deleteSubscriptions = true;
+ 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);
+}
+
+static void
+sendCloseSecureChannel(UA_Client *client) {
+ UA_SecureChannel *channel = &client->channel;
+ UA_CloseSecureChannelRequest request;
+ UA_CloseSecureChannelRequest_init(&request);
+ request.requestHeader.requestHandle = ++client->requestHandle;
+ request.requestHeader.timestamp = UA_DateTime_now();
+ request.requestHeader.timeoutHint = 10000;
+ request.requestHeader.authenticationToken = client->authenticationToken;
+ UA_SecureChannel_sendSymmetricMessage(channel, ++client->requestId,
+ UA_MESSAGETYPE_CLO, &request,
+ &UA_TYPES[UA_TYPES_CLOSESECURECHANNELREQUEST]);
+ UA_CloseSecureChannelRequest_deleteMembers(&request);
+ UA_SecureChannel_deleteMembersCleanup(&client->channel);
+}
+
+UA_StatusCode
+UA_Client_disconnect(UA_Client *client) {
+ /* Is a session established? */
+ if(client->state >= UA_CLIENTSTATE_SESSION) {
+ client->state = UA_CLIENTSTATE_SECURECHANNEL;
+ sendCloseSession(client);
+ }
+ UA_NodeId_deleteMembers(&client->authenticationToken);
+ client->requestHandle = 0;
+
+ /* Is a secure channel established? */
+ if(client->state >= UA_CLIENTSTATE_SECURECHANNEL) {
+ client->state = UA_CLIENTSTATE_CONNECTED;
+ sendCloseSecureChannel(client);
+ }
+
+ /* Close the TCP connection */
+ if(client->connection.state != UA_CONNECTION_CLOSED)
+ client->connection.close(&client->connection);
+
+#ifdef UA_ENABLE_SUBSCRIPTIONS
+// TODO REMOVE WHEN UA_SESSION_RECOVERY IS READY
+ /* We need to clean up the subscriptions */
+ UA_Client_Subscriptions_clean(client);
+#endif
+
+ setClientState(client, UA_CLIENTSTATE_DISCONNECTED);
+ return UA_STATUSCODE_GOOD;
+}
+
+UA_StatusCode
+UA_Client_close(UA_Client *client) {
+ client->requestHandle = 0;
+
+ if(client->state >= UA_CLIENTSTATE_SECURECHANNEL)
+ UA_SecureChannel_deleteMembersCleanup(&client->channel);
+
+ /* Close the TCP connection */
+ if(client->connection.state != UA_CONNECTION_CLOSED)
+ client->connection.close(&client->connection);
+
+#ifdef UA_ENABLE_SUBSCRIPTIONS
+// TODO REMOVE WHEN UA_SESSION_RECOVERY IS READY
+ /* We need to clean up the subscriptions */
+ UA_Client_Subscriptions_clean(client);
+#endif
+
+ setClientState(client, UA_CLIENTSTATE_DISCONNECTED);
+ return UA_STATUSCODE_GOOD;
+}
+
+/*********************************** amalgamated original file "/home/jvoe/open62541/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
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * Copyright 2017 (c) Julius Pfrommer, Fraunhofer IOSB
+ * Copyright 2017 (c) Mark Giraud, Fraunhofer IOSB
+ * Copyright 2017 (c) Stefan Profanter, fortiss GmbH
+ */
+
+
+UA_StatusCode
+UA_Client_getEndpoints(UA_Client *client, const char *serverUrl,
+ size_t* endpointDescriptionsSize,
+ UA_EndpointDescription** endpointDescriptions) {
+ UA_Boolean connected = (client->state > UA_CLIENTSTATE_DISCONNECTED);
+ /* Client is already connected to a different server */
+ if(connected && strncmp((const char*)client->endpointUrl.data, serverUrl,
+ client->endpointUrl.length) != 0) {
+ return UA_STATUSCODE_BADINVALIDARGUMENT;
+ }
+
+ UA_StatusCode retval;
+ if(!connected) {
+ retval = UA_Client_connectInternal(client, serverUrl, UA_FALSE, UA_FALSE);
+ if(retval != UA_STATUSCODE_GOOD)
+ return retval;
+ }
+ retval = UA_Client_getEndpointsInternal(client, endpointDescriptionsSize, endpointDescriptions);
+
+ if(!connected)
+ UA_Client_disconnect(client);
+ return retval;
+}
+
+UA_StatusCode
+UA_Client_findServers(UA_Client *client, const char *serverUrl,
+ size_t serverUrisSize, UA_String *serverUris,
+ size_t localeIdsSize, UA_String *localeIds,
+ size_t *registeredServersSize,
+ UA_ApplicationDescription **registeredServers) {
+ UA_Boolean connected = (client->state > UA_CLIENTSTATE_DISCONNECTED);
+ /* Client is already connected to a different server */
+ if(connected && strncmp((const char*)client->endpointUrl.data, serverUrl,
+ client->endpointUrl.length) != 0) {
+ return UA_STATUSCODE_BADINVALIDARGUMENT;
+ }
+
+ if(!connected) {
+ UA_StatusCode retval = UA_Client_connectInternal(client, serverUrl, UA_TRUE, UA_FALSE);
+ if(retval != UA_STATUSCODE_GOOD)
+ return retval;
+ }
+
+ /* Prepare the request */
+ UA_FindServersRequest request;
+ UA_FindServersRequest_init(&request);
+ request.serverUrisSize = serverUrisSize;
+ request.serverUris = serverUris;
+ request.localeIdsSize = localeIdsSize;
+ request.localeIds = localeIds;
+
+ /* Send the request */
+ UA_FindServersResponse response;
+ __UA_Client_Service(client, &request, &UA_TYPES[UA_TYPES_FINDSERVERSREQUEST],
+ &response, &UA_TYPES[UA_TYPES_FINDSERVERSRESPONSE]);
+
+ /* Process the response */
+ UA_StatusCode retval = response.responseHeader.serviceResult;
+ if(retval == UA_STATUSCODE_GOOD) {
+ *registeredServersSize = response.serversSize;
+ *registeredServers = response.servers;
+ response.serversSize = 0;
+ response.servers = NULL;
+ } else {
+ *registeredServersSize = 0;
+ *registeredServers = NULL;
+ }
+
+ /* Clean up */
+ UA_FindServersResponse_deleteMembers(&response);
+ if(!connected)
+ UA_Client_disconnect(client);
+ return retval;
+}
+
+UA_StatusCode
+UA_Client_findServersOnNetwork(UA_Client *client, const char *serverUrl,
+ UA_UInt32 startingRecordId, UA_UInt32 maxRecordsToReturn,
+ size_t serverCapabilityFilterSize, UA_String *serverCapabilityFilter,
+ size_t *serverOnNetworkSize, UA_ServerOnNetwork **serverOnNetwork) {
+ UA_Boolean connected = (client->state > UA_CLIENTSTATE_DISCONNECTED);
+ /* Client is already connected to a different server */
+ if(connected && strncmp((const char*)client->endpointUrl.data, serverUrl,
+ client->endpointUrl.length) != 0) {
+ return UA_STATUSCODE_BADINVALIDARGUMENT;
+ }
+
+ if(!connected) {
+ UA_StatusCode retval = UA_Client_connectInternal(client, serverUrl, UA_TRUE, UA_FALSE);
+ if(retval != UA_STATUSCODE_GOOD)
+ return retval;
+ }
+
+ /* Prepare the request */
+ UA_FindServersOnNetworkRequest request;
+ UA_FindServersOnNetworkRequest_init(&request);
+ request.startingRecordId = startingRecordId;
+ request.maxRecordsToReturn = maxRecordsToReturn;
+ request.serverCapabilityFilterSize = serverCapabilityFilterSize;
+ request.serverCapabilityFilter = serverCapabilityFilter;
+
+ /* Send the request */
+ UA_FindServersOnNetworkResponse response;
+ __UA_Client_Service(client, &request, &UA_TYPES[UA_TYPES_FINDSERVERSONNETWORKREQUEST],
+ &response, &UA_TYPES[UA_TYPES_FINDSERVERSONNETWORKRESPONSE]);
+
+ /* Process the response */
+ UA_StatusCode retval = response.responseHeader.serviceResult;
+ if(retval == UA_STATUSCODE_GOOD) {
+ *serverOnNetworkSize = response.serversSize;
+ *serverOnNetwork = response.servers;
+ response.serversSize = 0;
+ response.servers = NULL;
+ } else {
+ *serverOnNetworkSize = 0;
+ *serverOnNetwork = NULL;
+ }
+
+ /* Clean up */
+ UA_FindServersOnNetworkResponse_deleteMembers(&response);
+ if(!connected)
+ UA_Client_disconnect(client);
+ return retval;
+}
+
+/*********************************** amalgamated original file "/home/jvoe/open62541/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) Julius Pfrommer, Fraunhofer IOSB
+ * Copyright 2015 (c) Oleksiy Vasylyev
+ * Copyright 2017 (c) Florian Palm
+ * Copyright 2016 (c) Chris Iatrou
+ * Copyright 2017 (c) Stefan Profanter, fortiss GmbH
+ */
+
+
+UA_StatusCode
+UA_Client_NamespaceGetIndex(UA_Client *client, UA_String *namespaceUri,
+ UA_UInt16 *namespaceIndex) {
+ UA_ReadRequest request;
+ UA_ReadRequest_init(&request);
+ UA_ReadValueId id;
+ UA_ReadValueId_init(&id);
+ id.attributeId = UA_ATTRIBUTEID_VALUE;
+ id.nodeId = UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_NAMESPACEARRAY);
+ request.nodesToRead = &id;
+ request.nodesToReadSize = 1;
+
+ UA_ReadResponse response = UA_Client_Service_read(client, request);
+
+ UA_StatusCode retval = UA_STATUSCODE_GOOD;
+ if(response.responseHeader.serviceResult != UA_STATUSCODE_GOOD)
+ retval = response.responseHeader.serviceResult;
+ else if(response.resultsSize != 1 || !response.results[0].hasValue)
+ retval = UA_STATUSCODE_BADNODEATTRIBUTESINVALID;
+ else if(response.results[0].value.type != &UA_TYPES[UA_TYPES_STRING])
+ retval = UA_STATUSCODE_BADTYPEMISMATCH;
+
+ if(retval != UA_STATUSCODE_GOOD) {
+ UA_ReadResponse_deleteMembers(&response);
+ return retval;
+ }
+
+ retval = UA_STATUSCODE_BADNOTFOUND;
+ UA_String *ns = (UA_String *)response.results[0].value.data;
+ for(size_t i = 0; i < response.results[0].value.arrayLength; ++i) {
+ if(UA_String_equal(namespaceUri, &ns[i])) {
+ *namespaceIndex = (UA_UInt16)i;
+ retval = UA_STATUSCODE_GOOD;
+ break;
+ }
+ }
+
+ UA_ReadResponse_deleteMembers(&response);
+ return retval;
+}
+
+UA_StatusCode
+UA_Client_forEachChildNodeCall(UA_Client *client, UA_NodeId parentNodeId,
+ UA_NodeIteratorCallback callback, void *handle) {
+ UA_BrowseRequest bReq;
+ UA_BrowseRequest_init(&bReq);
+ bReq.requestedMaxReferencesPerNode = 0;
+ bReq.nodesToBrowse = UA_BrowseDescription_new();
+ bReq.nodesToBrowseSize = 1;
+ UA_NodeId_copy(&parentNodeId, &bReq.nodesToBrowse[0].nodeId);
+ bReq.nodesToBrowse[0].resultMask = UA_BROWSERESULTMASK_ALL; //return everything
+ bReq.nodesToBrowse[0].browseDirection = UA_BROWSEDIRECTION_BOTH;
+
+ UA_BrowseResponse bResp = UA_Client_Service_browse(client, bReq);
+
+ UA_StatusCode retval = bResp.responseHeader.serviceResult;
+ if(retval == UA_STATUSCODE_GOOD) {
+ for(size_t i = 0; i < bResp.resultsSize; ++i) {
+ for(size_t j = 0; j < bResp.results[i].referencesSize; ++j) {
+ UA_ReferenceDescription *ref = &bResp.results[i].references[j];
+ retval |= callback(ref->nodeId.nodeId, !ref->isForward,
+ ref->referenceTypeId, handle);
+ }
+ }
+ }
+
+ UA_BrowseRequest_deleteMembers(&bReq);
+ UA_BrowseResponse_deleteMembers(&bResp);
+ return retval;
+}
+
+/*******************/
+/* Node Management */
+/*******************/
+
+UA_StatusCode
+UA_Client_addReference(UA_Client *client, const UA_NodeId sourceNodeId,
+ const UA_NodeId referenceTypeId, UA_Boolean isForward,
+ const UA_String targetServerUri,
+ const UA_ExpandedNodeId targetNodeId,
+ UA_NodeClass targetNodeClass) {
+ UA_AddReferencesItem item;
+ UA_AddReferencesItem_init(&item);
+ item.sourceNodeId = sourceNodeId;
+ item.referenceTypeId = referenceTypeId;
+ item.isForward = isForward;
+ item.targetServerUri = targetServerUri;
+ item.targetNodeId = targetNodeId;
+ item.targetNodeClass = targetNodeClass;
+ UA_AddReferencesRequest request;
+ UA_AddReferencesRequest_init(&request);
+ request.referencesToAdd = &item;
+ request.referencesToAddSize = 1;
+ UA_AddReferencesResponse response = UA_Client_Service_addReferences(client, request);
+ UA_StatusCode retval = response.responseHeader.serviceResult;
+ if(retval != UA_STATUSCODE_GOOD) {
+ UA_AddReferencesResponse_deleteMembers(&response);
+ return retval;
+ }
+ if(response.resultsSize != 1) {
+ UA_AddReferencesResponse_deleteMembers(&response);
+ return UA_STATUSCODE_BADUNEXPECTEDERROR;
+ }
+ retval = response.results[0];
+ UA_AddReferencesResponse_deleteMembers(&response);
+ return retval;
+}
+
+UA_StatusCode
+UA_Client_deleteReference(UA_Client *client, const UA_NodeId sourceNodeId,
+ const UA_NodeId referenceTypeId, UA_Boolean isForward,
+ const UA_ExpandedNodeId targetNodeId,
+ UA_Boolean deleteBidirectional) {
+ UA_DeleteReferencesItem item;
+ UA_DeleteReferencesItem_init(&item);
+ item.sourceNodeId = sourceNodeId;
+ item.referenceTypeId = referenceTypeId;
+ item.isForward = isForward;
+ item.targetNodeId = targetNodeId;
+ item.deleteBidirectional = deleteBidirectional;
+ UA_DeleteReferencesRequest request;
+ UA_DeleteReferencesRequest_init(&request);
+ request.referencesToDelete = &item;
+ request.referencesToDeleteSize = 1;
+ UA_DeleteReferencesResponse response = UA_Client_Service_deleteReferences(client, request);
+ UA_StatusCode retval = response.responseHeader.serviceResult;
+ if(retval != UA_STATUSCODE_GOOD) {
+ UA_DeleteReferencesResponse_deleteMembers(&response);
+ return retval;
+ }
+ if(response.resultsSize != 1) {
+ UA_DeleteReferencesResponse_deleteMembers(&response);
+ return UA_STATUSCODE_BADUNEXPECTEDERROR;
+ }
+ retval = response.results[0];
+ UA_DeleteReferencesResponse_deleteMembers(&response);
+ return retval;
+}
+
+UA_StatusCode
+UA_Client_deleteNode(UA_Client *client, const UA_NodeId nodeId,
+ UA_Boolean deleteTargetReferences) {
+ UA_DeleteNodesItem item;
+ UA_DeleteNodesItem_init(&item);
+ item.nodeId = nodeId;
+ item.deleteTargetReferences = deleteTargetReferences;
+ UA_DeleteNodesRequest request;
+ UA_DeleteNodesRequest_init(&request);
+ request.nodesToDelete = &item;
+ request.nodesToDeleteSize = 1;
+ UA_DeleteNodesResponse response = UA_Client_Service_deleteNodes(client, request);
+ UA_StatusCode retval = response.responseHeader.serviceResult;
+ if(retval != UA_STATUSCODE_GOOD) {
+ UA_DeleteNodesResponse_deleteMembers(&response);
+ return retval;
+ }
+ if(response.resultsSize != 1) {
+ UA_DeleteNodesResponse_deleteMembers(&response);
+ return UA_STATUSCODE_BADUNEXPECTEDERROR;
+ }
+ retval = response.results[0];
+ UA_DeleteNodesResponse_deleteMembers(&response);
+ return retval;
+}
+
+UA_StatusCode
+__UA_Client_addNode(UA_Client *client, 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, UA_NodeId *outNewNodeId) {
+ UA_AddNodesRequest request;
+ UA_AddNodesRequest_init(&request);
+ UA_AddNodesItem item;
+ UA_AddNodesItem_init(&item);
+ item.parentNodeId.nodeId = parentNodeId;
+ item.referenceTypeId = referenceTypeId;
+ item.requestedNewNodeId.nodeId = requestedNewNodeId;
+ item.browseName = browseName;
+ item.nodeClass = nodeClass;
+ 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; // hack. is not written into.
+ request.nodesToAdd = &item;
+ request.nodesToAddSize = 1;
+ UA_AddNodesResponse response = UA_Client_Service_addNodes(client, request);
+
+ UA_StatusCode retval = response.responseHeader.serviceResult;
+ if(retval != UA_STATUSCODE_GOOD) {
+ UA_AddNodesResponse_deleteMembers(&response);
+ return retval;
+ }
+
+ if(response.resultsSize != 1) {
+ UA_AddNodesResponse_deleteMembers(&response);
+ return UA_STATUSCODE_BADUNEXPECTEDERROR;
+ }
+
+ /* Move the id of the created node */
+ retval = response.results[0].statusCode;
+ if(retval == UA_STATUSCODE_GOOD && outNewNodeId) {
+ *outNewNodeId = response.results[0].addedNodeId;
+ UA_NodeId_init(&response.results[0].addedNodeId);
+ }
+
+ UA_AddNodesResponse_deleteMembers(&response);
+ return retval;
+}
+
+/********/
+/* Call */
+/********/
+
+#ifdef UA_ENABLE_METHODCALLS
+
+UA_StatusCode
+UA_Client_call(UA_Client *client, const UA_NodeId objectId,
+ const UA_NodeId methodId, size_t inputSize,
+ const UA_Variant *input, size_t *outputSize,
+ UA_Variant **output) {
+ /* Set up the request */
+ UA_CallRequest request;
+ UA_CallRequest_init(&request);
+ UA_CallMethodRequest item;
+ UA_CallMethodRequest_init(&item);
+ item.methodId = methodId;
+ item.objectId = objectId;
+ item.inputArguments = (UA_Variant *)(void*)(uintptr_t)input; // cast const...
+ item.inputArgumentsSize = inputSize;
+ request.methodsToCall = &item;
+ request.methodsToCallSize = 1;
+
+ /* Call the service */
+ UA_CallResponse response = UA_Client_Service_call(client, request);
+ UA_StatusCode retval = response.responseHeader.serviceResult;
+ if(retval == UA_STATUSCODE_GOOD) {
+ if(response.resultsSize == 1)
+ retval = response.results[0].statusCode;
+ else
+ retval = UA_STATUSCODE_BADUNEXPECTEDERROR;
+ }
+ if(retval != UA_STATUSCODE_GOOD) {
+ UA_CallResponse_deleteMembers(&response);
+ return retval;
+ }
+
+ /* Move the output arguments */
+ if(output != NULL && outputSize != NULL) {
+ *output = response.results[0].outputArguments;
+ *outputSize = response.results[0].outputArgumentsSize;
+ response.results[0].outputArguments = NULL;
+ response.results[0].outputArgumentsSize = 0;
+ }
+ UA_CallResponse_deleteMembers(&response);
+ return retval;
+}
+
+#endif
+
+/********************/
+/* Write Attributes */
+/********************/
+
+UA_StatusCode
+__UA_Client_writeAttribute(UA_Client *client, const UA_NodeId *nodeId,
+ UA_AttributeId attributeId, const void *in,
+ const UA_DataType *inDataType) {
+ if(!in)
+ return UA_STATUSCODE_BADTYPEMISMATCH;
+
+ UA_WriteValue wValue;
+ UA_WriteValue_init(&wValue);
+ wValue.nodeId = *nodeId;
+ wValue.attributeId = attributeId;
+ if(attributeId == UA_ATTRIBUTEID_VALUE)
+ wValue.value.value = *(const UA_Variant*)in;
+ else
+ /* hack. is never written into. */
+ UA_Variant_setScalar(&wValue.value.value, (void*)(uintptr_t)in, inDataType);
+ wValue.value.hasValue = true;
+ UA_WriteRequest wReq;
+ UA_WriteRequest_init(&wReq);
+ wReq.nodesToWrite = &wValue;
+ wReq.nodesToWriteSize = 1;
+
+ UA_WriteResponse wResp = UA_Client_Service_write(client, wReq);
+
+ UA_StatusCode retval = wResp.responseHeader.serviceResult;
+ if(retval == UA_STATUSCODE_GOOD) {
+ if(wResp.resultsSize == 1)
+ retval = wResp.results[0];
+ else
+ retval = UA_STATUSCODE_BADUNEXPECTEDERROR;
+ }
+
+ UA_WriteResponse_deleteMembers(&wResp);
+ return retval;
+}
+
+UA_StatusCode
+UA_Client_writeArrayDimensionsAttribute(UA_Client *client, const UA_NodeId nodeId,
+ size_t newArrayDimensionsSize,
+ const UA_UInt32 *newArrayDimensions) {
+ if(!newArrayDimensions)
+ return UA_STATUSCODE_BADTYPEMISMATCH;
+
+ UA_WriteValue wValue;
+ UA_WriteValue_init(&wValue);
+ wValue.nodeId = nodeId;
+ wValue.attributeId = UA_ATTRIBUTEID_ARRAYDIMENSIONS;
+ UA_Variant_setArray(&wValue.value.value, (void*)(uintptr_t)newArrayDimensions,
+ newArrayDimensionsSize, &UA_TYPES[UA_TYPES_UINT32]);
+ wValue.value.hasValue = true;
+ UA_WriteRequest wReq;
+ UA_WriteRequest_init(&wReq);
+ wReq.nodesToWrite = &wValue;
+ wReq.nodesToWriteSize = 1;
+
+ UA_WriteResponse wResp = UA_Client_Service_write(client, wReq);
+
+ UA_StatusCode retval = wResp.responseHeader.serviceResult;
+ if(retval == UA_STATUSCODE_GOOD) {
+ if(wResp.resultsSize == 1)
+ retval = wResp.results[0];
+ else
+ retval = UA_STATUSCODE_BADUNEXPECTEDERROR;
+ }
+ UA_WriteResponse_deleteMembers(&wResp);
+ return retval;
+}
+
+/*******************/
+/* Read Attributes */
+/*******************/
+
+UA_StatusCode
+__UA_Client_readAttribute(UA_Client *client, const UA_NodeId *nodeId,
+ UA_AttributeId attributeId, void *out,
+ const UA_DataType *outDataType) {
+ 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;
+ UA_ReadResponse response = UA_Client_Service_read(client, request);
+ UA_StatusCode retval = response.responseHeader.serviceResult;
+ if(retval == UA_STATUSCODE_GOOD) {
+ if(response.resultsSize == 1)
+ retval = response.results[0].status;
+ else
+ retval = UA_STATUSCODE_BADUNEXPECTEDERROR;
+ }
+ if(retval != UA_STATUSCODE_GOOD) {
+ UA_ReadResponse_deleteMembers(&response);
+ return retval;
+ }
+
+ /* Set the StatusCode */
+ UA_DataValue *res = response.results;
+ if(res->hasStatus)
+ retval = res->status;
+
+ /* Return early of no value is given */
+ if(!res->hasValue) {
+ if(retval == UA_STATUSCODE_GOOD)
+ retval = UA_STATUSCODE_BADUNEXPECTEDERROR;
+ UA_ReadResponse_deleteMembers(&response);
+ return retval;
+ }
+
+ /* Copy value into out */
+ if(attributeId == UA_ATTRIBUTEID_VALUE) {
+ memcpy(out, &res->value, sizeof(UA_Variant));
+ UA_Variant_init(&res->value);
+ } else if(attributeId == UA_ATTRIBUTEID_NODECLASS) {
+ memcpy(out, (UA_NodeClass*)res->value.data, sizeof(UA_NodeClass));
+ } else if(UA_Variant_isScalar(&res->value) &&
+ res->value.type == outDataType) {
+ memcpy(out, res->value.data, res->value.type->memSize);
+ UA_free(res->value.data);
+ res->value.data = NULL;
+ } else {
+ retval = UA_STATUSCODE_BADUNEXPECTEDERROR;
+ }
+
+ UA_ReadResponse_deleteMembers(&response);
+ return retval;
+}
+
+static UA_StatusCode
+processReadArrayDimensionsResult(UA_ReadResponse *response,
+ UA_UInt32 **outArrayDimensions,
+ size_t *outArrayDimensionsSize) {
+ UA_StatusCode retval = response->responseHeader.serviceResult;
+ if(retval != UA_STATUSCODE_GOOD)
+ return retval;
+
+ if(response->resultsSize != 1)
+ return UA_STATUSCODE_BADUNEXPECTEDERROR;
+
+ retval = response->results[0].status;
+ if(retval != UA_STATUSCODE_GOOD)
+ return retval;
+
+ UA_DataValue *res = &response->results[0];
+ if(!res->hasValue ||
+ UA_Variant_isScalar(&res->value) ||
+ res->value.type != &UA_TYPES[UA_TYPES_UINT32])
+ return UA_STATUSCODE_BADUNEXPECTEDERROR;
+
+ /* Move results */
+ *outArrayDimensions = (UA_UInt32*)res->value.data;
+ *outArrayDimensionsSize = res->value.arrayLength;
+ res->value.data = NULL;
+ res->value.arrayLength = 0;
+ return UA_STATUSCODE_GOOD;
+}
+
+UA_StatusCode
+UA_Client_readArrayDimensionsAttribute(UA_Client *client, const UA_NodeId nodeId,
+ size_t *outArrayDimensionsSize,
+ UA_UInt32 **outArrayDimensions) {
+ UA_ReadValueId item;
+ UA_ReadValueId_init(&item);
+ item.nodeId = nodeId;
+ item.attributeId = UA_ATTRIBUTEID_ARRAYDIMENSIONS;
+ UA_ReadRequest request;
+ UA_ReadRequest_init(&request);
+ request.nodesToRead = &item;
+ request.nodesToReadSize = 1;
+
+ UA_ReadResponse response = UA_Client_Service_read(client, request);
+ UA_StatusCode retval = processReadArrayDimensionsResult(&response, outArrayDimensions,
+ outArrayDimensionsSize);
+ UA_ReadResponse_deleteMembers(&response);
+ return retval;
+}
+
+/*********************************** amalgamated original file "/home/jvoe/open62541/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
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * Copyright 2015-2018 (c) Julius Pfrommer, Fraunhofer IOSB
+ * Copyright 2015 (c) Oleksiy Vasylyev
+ * Copyright 2016 (c) Sten Grüner
+ * Copyright 2017-2018 (c) Thomas Stalder, Blue Time Concept SA
+ * Copyright 2016-2017 (c) Florian Palm
+ * Copyright 2017 (c) Frank Meerkötter
+ * Copyright 2017 (c) Stefan Profanter, fortiss GmbH
+ */
+
+
+#ifdef UA_ENABLE_SUBSCRIPTIONS /* conditional compilation */
+
+/*****************/
+/* Subscriptions */
+/*****************/
+
+UA_CreateSubscriptionResponse UA_EXPORT
+UA_Client_Subscriptions_create(UA_Client *client,
+ const UA_CreateSubscriptionRequest request,
+ void *subscriptionContext,
+ UA_Client_StatusChangeNotificationCallback statusChangeCallback,
+ UA_Client_DeleteSubscriptionCallback deleteCallback) {
+ UA_CreateSubscriptionResponse response;
+ UA_CreateSubscriptionResponse_init(&response);
+
+ /* Allocate the internal representation */
+ UA_Client_Subscription *newSub = (UA_Client_Subscription*)
+ UA_malloc(sizeof(UA_Client_Subscription));
+ if(!newSub) {
+ response.responseHeader.serviceResult = UA_STATUSCODE_BADOUTOFMEMORY;
+ return response;
+ }
+
+ /* Send the request as a synchronous service call */
+ __UA_Client_Service(client,
+ &request, &UA_TYPES[UA_TYPES_CREATESUBSCRIPTIONREQUEST],
+ &response, &UA_TYPES[UA_TYPES_CREATESUBSCRIPTIONRESPONSE]);
+ if(response.responseHeader.serviceResult != UA_STATUSCODE_GOOD) {
+ UA_free(newSub);
+ return response;
+ }
+
+ /* Prepare the internal representation */
+ newSub->context = subscriptionContext;
+ newSub->subscriptionId = response.subscriptionId;
+ newSub->sequenceNumber = 0;
+ newSub->lastActivity = UA_DateTime_nowMonotonic();
+ newSub->statusChangeCallback = statusChangeCallback;
+ newSub->deleteCallback = deleteCallback;
+ newSub->publishingInterval = response.revisedPublishingInterval;
+ newSub->maxKeepAliveCount = response.revisedMaxKeepAliveCount;
+ LIST_INIT(&newSub->monitoredItems);
+ LIST_INSERT_HEAD(&client->subscriptions, newSub, listEntry);
+
+ return response;
+}
+
+static UA_Client_Subscription *
+findSubscription(const UA_Client *client, UA_UInt32 subscriptionId) {
+ UA_Client_Subscription *sub = NULL;
+ LIST_FOREACH(sub, &client->subscriptions, listEntry) {
+ if(sub->subscriptionId == subscriptionId)
+ break;
+ }
+ return sub;
+}
+
+UA_ModifySubscriptionResponse UA_EXPORT
+UA_Client_Subscriptions_modify(UA_Client *client, const UA_ModifySubscriptionRequest request) {
+ UA_ModifySubscriptionResponse response;
+ UA_ModifySubscriptionResponse_init(&response);
+
+ /* Find the internal representation */
+ UA_Client_Subscription *sub = findSubscription(client, request.subscriptionId);
+ if(!sub) {
+ response.responseHeader.serviceResult = UA_STATUSCODE_BADSUBSCRIPTIONIDINVALID;
+ return response;
+ }
+
+ /* Call the service */
+ __UA_Client_Service(client,
+ &request, &UA_TYPES[UA_TYPES_MODIFYSUBSCRIPTIONREQUEST],
+ &response, &UA_TYPES[UA_TYPES_MODIFYSUBSCRIPTIONRESPONSE]);
+
+ /* Adjust the internal representation */
+ sub->publishingInterval = response.revisedPublishingInterval;
+ sub->maxKeepAliveCount = response.revisedMaxKeepAliveCount;
+ return response;
+}
+
+static void
+UA_Client_Subscription_deleteInternal(UA_Client *client, UA_Client_Subscription *sub) {
+ /* Remove the MonitoredItems */
+ UA_Client_MonitoredItem *mon, *mon_tmp;
+ LIST_FOREACH_SAFE(mon, &sub->monitoredItems, listEntry, mon_tmp)
+ UA_Client_MonitoredItem_remove(client, sub, mon);
+
+ /* Call the delete callback */
+ if(sub->deleteCallback)
+ sub->deleteCallback(client, sub->subscriptionId, sub->context);
+
+ /* Remove */
+ LIST_REMOVE(sub, listEntry);
+ UA_free(sub);
+}
+
+UA_DeleteSubscriptionsResponse UA_EXPORT
+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);
+
+ /* temporary remove the subscriptions from the list */
+ for(size_t i = 0; i < request.subscriptionIdsSize; i++) {
+ subs[i] = findSubscription(client, request.subscriptionIds[i]);
+ if (subs[i])
+ LIST_REMOVE(subs[i], listEntry);
+ }
+
+ /* Send the request */
+ UA_DeleteSubscriptionsResponse response;
+ __UA_Client_Service(client,
+ &request, &UA_TYPES[UA_TYPES_DELETESUBSCRIPTIONSREQUEST],
+ &response, &UA_TYPES[UA_TYPES_DELETESUBSCRIPTIONSRESPONSE]);
+ if(response.responseHeader.serviceResult != UA_STATUSCODE_GOOD)
+ goto cleanup;
+
+ if(request.subscriptionIdsSize != response.resultsSize) {
+ response.responseHeader.serviceResult = UA_STATUSCODE_BADINTERNALERROR;
+ goto cleanup;
+ }
+
+ /* 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);
+ continue;
+ }
+
+ if(!subs[i]) {
+ UA_LOG_INFO(client->config.logger, UA_LOGCATEGORY_CLIENT,
+ "No internal representation of subscription %u",
+ request.subscriptionIds[i]);
+ continue;
+ } else {
+ LIST_INSERT_HEAD(&client->subscriptions, subs[i], listEntry);
+ }
+
+ UA_Client_Subscription_deleteInternal(client, subs[i]);
+ }
+
+ return response;
+
+cleanup:
+ for(size_t i = 0; i < request.subscriptionIdsSize; i++) {
+ if (subs[i]) {
+ LIST_INSERT_HEAD(&client->subscriptions, subs[i], listEntry);
+ }
+ }
+ return response;
+}
+
+UA_StatusCode UA_EXPORT
+UA_Client_Subscriptions_deleteSingle(UA_Client *client, UA_UInt32 subscriptionId) {
+ UA_DeleteSubscriptionsRequest request;
+ UA_DeleteSubscriptionsRequest_init(&request);
+ request.subscriptionIds = &subscriptionId;
+ request.subscriptionIdsSize = 1;
+
+ UA_DeleteSubscriptionsResponse response =
+ UA_Client_Subscriptions_delete(client, request);
+
+ UA_StatusCode retval = response.responseHeader.serviceResult;
+ if(retval != UA_STATUSCODE_GOOD) {
+ UA_DeleteSubscriptionsResponse_deleteMembers(&response);
+ return retval;
+ }
+
+ if(response.resultsSize != 1) {
+ UA_DeleteSubscriptionsResponse_deleteMembers(&response);
+ return UA_STATUSCODE_BADINTERNALERROR;
+ }
+
+ retval = response.results[0];
+ UA_DeleteSubscriptionsResponse_deleteMembers(&response);
+ return retval;
+}
+
+/******************/
+/* MonitoredItems */
+/******************/
+
+void
+UA_Client_MonitoredItem_remove(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,
+ mon->monitoredItemId, mon->context);
+ UA_free(mon);
+}
+
+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_CreateMonitoredItemsResponse_init(response);
+
+ if (!request->itemsToCreateSize) {
+ response->responseHeader.serviceResult = UA_STATUSCODE_BADINTERNALERROR;
+ return;
+ }
+
+ /* Fix clang warning */
+ size_t itemsToCreateSize = request->itemsToCreateSize;
+ UA_Client_Subscription *sub = NULL;
+
+ /* Allocate the memory for internal representations */
+ UA_STACKARRAY(UA_Client_MonitoredItem*, mis, itemsToCreateSize);
+ memset(mis, 0, sizeof(void*) * itemsToCreateSize);
+ for(size_t i = 0; i < itemsToCreateSize; i++) {
+ mis[i] = (UA_Client_MonitoredItem*)UA_malloc(sizeof(UA_Client_MonitoredItem));
+ if(!mis[i]) {
+ response->responseHeader.serviceResult = UA_STATUSCODE_BADOUTOFMEMORY;
+ goto cleanup;
+ }
+ }
+
+ /* Get the subscription */
+ sub = findSubscription(client, request->subscriptionId);
+ if(!sub) {
+ response->responseHeader.serviceResult = UA_STATUSCODE_BADSUBSCRIPTIONIDINVALID;
+ goto cleanup;
+ }
+
+ /* Set the clientHandle */
+ for(size_t i = 0; i < itemsToCreateSize; i++)
+ request->itemsToCreate[i].requestedParameters.clientHandle = ++(client->monitoredItemHandles);
+
+ /* Call the service */
+ __UA_Client_Service(client, request, &UA_TYPES[UA_TYPES_CREATEMONITOREDITEMSREQUEST],
+ response, &UA_TYPES[UA_TYPES_CREATEMONITOREDITEMSRESPONSE]);
+ if(response->responseHeader.serviceResult != UA_STATUSCODE_GOOD)
+ goto cleanup;
+
+ if(response->resultsSize != itemsToCreateSize) {
+ response->responseHeader.serviceResult = UA_STATUSCODE_BADINTERNALERROR;
+ goto cleanup;
+ }
+
+ /* Add internally */
+ for(size_t i = 0; i < 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;
+ continue;
+ }
+
+ UA_Client_MonitoredItem *newMon = mis[i];
+ newMon->clientHandle = request->itemsToCreate[i].requestedParameters.clientHandle;
+ newMon->monitoredItemId = response->results[i].monitoredItemId;
+ newMon->context = contexts[i];
+ newMon->deleteCallback = deleteCallbacks[i];
+ newMon->handler.dataChangeCallback =
+ (UA_Client_DataChangeNotificationCallback)(uintptr_t)handlingCallbacks[i];
+ newMon->isEventMonitoredItem =
+ (request->itemsToCreate[i].itemToMonitor.attributeId == UA_ATTRIBUTEID_EVENTNOTIFIER);
+ LIST_INSERT_HEAD(&sub->monitoredItems, newMon, listEntry);
+ }
+
+ return;
+
+ cleanup:
+ for(size_t i = 0; i < itemsToCreateSize; i++) {
+ if (deleteCallbacks[i]) {
+ if (sub)
+ deleteCallbacks[i](client, sub->subscriptionId, sub->context, 0, contexts[i]);
+ else
+ deleteCallbacks[i](client, 0, NULL, 0, contexts[i]);
+ }
+ if(mis[i])
+ UA_free(mis[i]);
+ }
+}
+
+UA_CreateMonitoredItemsResponse UA_EXPORT
+UA_Client_MonitoredItems_createDataChanges(UA_Client *client,
+ const UA_CreateMonitoredItemsRequest request, void **contexts,
+ UA_Client_DataChangeNotificationCallback *callbacks,
+ UA_Client_DeleteMonitoredItemCallback *deleteCallbacks) {
+ UA_CreateMonitoredItemsResponse response;
+ __UA_Client_MonitoredItems_create(client, &request, contexts,
+ (void**)(uintptr_t)callbacks, deleteCallbacks, &response);
+ return response;
+}
+
+UA_MonitoredItemCreateResult UA_EXPORT
+UA_Client_MonitoredItems_createDataChange(UA_Client *client, UA_UInt32 subscriptionId,
+ UA_TimestampsToReturn timestampsToReturn, const UA_MonitoredItemCreateRequest item,
+ void *context, UA_Client_DataChangeNotificationCallback callback,
+ UA_Client_DeleteMonitoredItemCallback deleteCallback) {
+ UA_CreateMonitoredItemsRequest request;
+ UA_CreateMonitoredItemsRequest_init(&request);
+ request.subscriptionId = subscriptionId;
+ request.timestampsToReturn = timestampsToReturn;
+ request.itemsToCreate = (UA_MonitoredItemCreateRequest*)(uintptr_t)&item;
+ request.itemsToCreateSize = 1;
+ UA_CreateMonitoredItemsResponse response =
+ UA_Client_MonitoredItems_createDataChanges(client, request, &context,
+ &callback, &deleteCallback);
+ UA_MonitoredItemCreateResult result;
+ UA_MonitoredItemCreateResult_init(&result);
+ if(response.responseHeader.serviceResult != UA_STATUSCODE_GOOD)
+ result.statusCode = response.responseHeader.serviceResult;
+
+ if(result.statusCode == UA_STATUSCODE_GOOD &&
+ response.resultsSize != 1)
+ result.statusCode = UA_STATUSCODE_BADINTERNALERROR;
+
+ if(result.statusCode == UA_STATUSCODE_GOOD)
+ UA_MonitoredItemCreateResult_copy(&response.results[0] , &result);
+ UA_CreateMonitoredItemsResponse_deleteMembers(&response);
+ return result;
+}
+
+UA_CreateMonitoredItemsResponse UA_EXPORT
+UA_Client_MonitoredItems_createEvents(UA_Client *client,
+ const UA_CreateMonitoredItemsRequest request, void **contexts,
+ UA_Client_EventNotificationCallback *callbacks,
+ UA_Client_DeleteMonitoredItemCallback *deleteCallbacks) {
+ UA_CreateMonitoredItemsResponse response;
+ __UA_Client_MonitoredItems_create(client, &request, contexts,
+ (void**)(uintptr_t)callbacks, deleteCallbacks, &response);
+ return response;
+}
+
+UA_MonitoredItemCreateResult UA_EXPORT
+UA_Client_MonitoredItems_createEvent(UA_Client *client, UA_UInt32 subscriptionId,
+ UA_TimestampsToReturn timestampsToReturn, const UA_MonitoredItemCreateRequest item,
+ void *context, UA_Client_EventNotificationCallback callback,
+ UA_Client_DeleteMonitoredItemCallback deleteCallback) {
+ UA_CreateMonitoredItemsRequest request;
+ UA_CreateMonitoredItemsRequest_init(&request);
+ request.subscriptionId = subscriptionId;
+ request.timestampsToReturn = timestampsToReturn;
+ request.itemsToCreate = (UA_MonitoredItemCreateRequest*)(uintptr_t)&item;
+ request.itemsToCreateSize = 1;
+ UA_CreateMonitoredItemsResponse response =
+ UA_Client_MonitoredItems_createEvents(client, request, &context,
+ &callback, &deleteCallback);
+ UA_MonitoredItemCreateResult result;
+ UA_MonitoredItemCreateResult_copy(response.results , &result);
+ UA_CreateMonitoredItemsResponse_deleteMembers(&response);
+ return result;
+}
+
+UA_DeleteMonitoredItemsResponse UA_EXPORT
+UA_Client_MonitoredItems_delete(UA_Client *client, const UA_DeleteMonitoredItemsRequest request) {
+ /* Send the request */
+ UA_DeleteMonitoredItemsResponse response;
+ __UA_Client_Service(client, &request, &UA_TYPES[UA_TYPES_DELETEMONITOREDITEMSREQUEST],
+ &response, &UA_TYPES[UA_TYPES_DELETEMONITOREDITEMSRESPONSE]);
+ if(response.responseHeader.serviceResult != UA_STATUSCODE_GOOD)
+ return response;
+
+ UA_Client_Subscription *sub = findSubscription(client, request.subscriptionId);
+ if(!sub) {
+ UA_LOG_INFO(client->config.logger, UA_LOGCATEGORY_CLIENT,
+ "No internal representation of subscription %u",
+ request.subscriptionId);
+ return response;
+ }
+
+ /* Loop over deleted MonitoredItems */
+ for(size_t i = 0; i < response.resultsSize; i++) {
+ if(response.results[i] != UA_STATUSCODE_GOOD &&
+ response.results[i] != UA_STATUSCODE_BADMONITOREDITEMIDINVALID) {
+ continue;
+ }
+
+#ifndef __clang_analyzer__
+ /* Delete the internal representation */
+ UA_Client_MonitoredItem *mon;
+ LIST_FOREACH(mon, &sub->monitoredItems, listEntry) {
+ if(mon->monitoredItemId == request.monitoredItemIds[i]) {
+ UA_Client_MonitoredItem_remove(client, sub, mon);
+ break;
+ }
+ }
+#endif
+ }
+
+ return response;
+}
+
+UA_StatusCode UA_EXPORT
+UA_Client_MonitoredItems_deleteSingle(UA_Client *client, UA_UInt32 subscriptionId, UA_UInt32 monitoredItemId) {
+ UA_DeleteMonitoredItemsRequest request;
+ UA_DeleteMonitoredItemsRequest_init(&request);
+ request.subscriptionId = subscriptionId;
+ request.monitoredItemIds = &monitoredItemId;
+ request.monitoredItemIdsSize = 1;
+
+ UA_DeleteMonitoredItemsResponse response =
+ UA_Client_MonitoredItems_delete(client, request);
+
+ UA_StatusCode retval = response.responseHeader.serviceResult;
+ if(retval != UA_STATUSCODE_GOOD) {
+ UA_DeleteMonitoredItemsResponse_deleteMembers(&response);
+ return retval;
+ }
+
+ if(response.resultsSize != 1) {
+ UA_DeleteMonitoredItemsResponse_deleteMembers(&response);
+ return UA_STATUSCODE_BADINTERNALERROR;
+ }
+
+ retval = response.results[0];
+ UA_DeleteMonitoredItemsResponse_deleteMembers(&response);
+ return retval;
+}
+
+/*************************************/
+/* Async Processing of Notifications */
+/*************************************/
+
+/* Assume the request is already initialized */
+UA_StatusCode
+UA_Client_preparePublishRequest(UA_Client *client, UA_PublishRequest *request) {
+ /* Count acks */
+ UA_Client_NotificationsAckNumber *ack;
+ LIST_FOREACH(ack, &client->pendingNotificationsAcks, listEntry)
+ ++request->subscriptionAcknowledgementsSize;
+
+ /* Create the array. Returns a sentinel pointer if the length is zero. */
+ request->subscriptionAcknowledgements = (UA_SubscriptionAcknowledgement*)
+ UA_Array_new(request->subscriptionAcknowledgementsSize,
+ &UA_TYPES[UA_TYPES_SUBSCRIPTIONACKNOWLEDGEMENT]);
+ if(!request->subscriptionAcknowledgements) {
+ request->subscriptionAcknowledgementsSize = 0;
+ return UA_STATUSCODE_BADOUTOFMEMORY;
+ }
+
+ size_t i = 0;
+ UA_Client_NotificationsAckNumber *ack_tmp;
+ LIST_FOREACH_SAFE(ack, &client->pendingNotificationsAcks, listEntry, ack_tmp) {
+ request->subscriptionAcknowledgements[i].sequenceNumber = ack->subAck.sequenceNumber;
+ request->subscriptionAcknowledgements[i].subscriptionId = ack->subAck.subscriptionId;
+ ++i;
+ LIST_REMOVE(ack, listEntry);
+ UA_free(ack);
+ }
+ return UA_STATUSCODE_GOOD;
+}
+
+/* According to OPC Unified Architecture, Part 4 5.13.1.1 i) */
+/* The value 0 is never used for the sequence number */
+static UA_UInt32
+UA_Client_Subscriptions_nextSequenceNumber(UA_UInt32 sequenceNumber) {
+ UA_UInt32 nextSequenceNumber = sequenceNumber + 1;
+ if(nextSequenceNumber == 0)
+ nextSequenceNumber = 1;
+ return nextSequenceNumber;
+}
+
+static void
+processDataChangeNotification(UA_Client *client, UA_Client_Subscription *sub,
+ UA_DataChangeNotification *dataChangeNotification) {
+ for(size_t j = 0; j < dataChangeNotification->monitoredItemsSize; ++j) {
+ UA_MonitoredItemNotification *min = &dataChangeNotification->monitoredItems[j];
+
+ /* Find the MonitoredItem */
+ UA_Client_MonitoredItem *mon;
+ LIST_FOREACH(mon, &sub->monitoredItems, listEntry) {
+ if(mon->clientHandle == min->clientHandle)
+ break;
+ }
+
+ if(!mon) {
+ UA_LOG_DEBUG(client->config.logger, UA_LOGCATEGORY_CLIENT,
+ "Could not process a notification with clienthandle %u on subscription %u",
+ 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.");
+ continue;
+ }
+
+ mon->handler.dataChangeCallback(client, sub->subscriptionId, sub->context,
+ mon->monitoredItemId, mon->context,
+ &min->value);
+ }
+}
+
+static void
+processEventNotification(UA_Client *client, UA_Client_Subscription *sub,
+ UA_EventNotificationList *eventNotificationList) {
+ for(size_t j = 0; j < eventNotificationList->eventsSize; ++j) {
+ UA_EventFieldList *eventFieldList = &eventNotificationList->events[j];
+
+ /* Find the MonitoredItem */
+ UA_Client_MonitoredItem *mon;
+ LIST_FOREACH(mon, &sub->monitoredItems, listEntry) {
+ if(mon->monitoredItemId == eventFieldList->clientHandle)
+ break;
+ }
+
+ if(!mon) {
+ UA_LOG_DEBUG(client->config.logger, UA_LOGCATEGORY_CLIENT,
+ "Could not process a notification with clienthandle %u on subscription %u",
+ eventFieldList->clientHandle, sub->subscriptionId);
+ continue;
+ }
+
+ if(!mon->isEventMonitoredItem) {
+ UA_LOG_DEBUG(client->config.logger, UA_LOGCATEGORY_CLIENT,
+ "MonitoredItem is configured for DataChanges. But received a "
+ "EventNotification.");
+ continue;
+ }
+
+ mon->handler.eventCallback(client, sub->subscriptionId, sub->context,
+ mon->monitoredItemId, mon->context,
+ eventFieldList->eventFieldsSize,
+ eventFieldList->eventFields);
+ }
+}
+
+static void
+processNotificationMessage(UA_Client *client, UA_Client_Subscription *sub,
+ UA_ExtensionObject *msg) {
+ if(msg->encoding != UA_EXTENSIONOBJECT_DECODED)
+ return;
+
+ /* Handle DataChangeNotification */
+ if(msg->content.decoded.type == &UA_TYPES[UA_TYPES_DATACHANGENOTIFICATION]) {
+ UA_DataChangeNotification *dataChangeNotification =
+ (UA_DataChangeNotification *)msg->content.decoded.data;
+ processDataChangeNotification(client, sub, dataChangeNotification);
+ return;
+ }
+
+ /* Handle EventNotification */
+ if(msg->content.decoded.type == &UA_TYPES[UA_TYPES_EVENTNOTIFICATIONLIST]) {
+ UA_EventNotificationList *eventNotificationList =
+ (UA_EventNotificationList *)msg->content.decoded.data;
+ processEventNotification(client, sub, eventNotificationList);
+ return;
+ }
+
+ /* Handle StatusChangeNotification */
+ if(msg->content.decoded.type == &UA_TYPES[UA_TYPES_STATUSCHANGENOTIFICATION]) {
+ if(sub->statusChangeCallback) {
+ sub->statusChangeCallback(client, sub->subscriptionId, sub->context,
+ (UA_StatusChangeNotification*)msg->content.decoded.data);
+ } else {
+ UA_LOG_WARNING(client->config.logger, UA_LOGCATEGORY_CLIENT,
+ "Dropped a StatusChangeNotification since no callback is registered");
+ }
+ return;
+ }
+
+ UA_LOG_WARNING(client->config.logger, UA_LOGCATEGORY_CLIENT,
+ "Unknown notification message type");
+}
+
+void
+UA_Client_Subscriptions_processPublishResponse(UA_Client *client, UA_PublishRequest *request,
+ UA_PublishResponse *response) {
+ UA_NotificationMessage *msg = &response->notificationMessage;
+
+ client->currentlyOutStandingPublishRequests--;
+
+ if(response->responseHeader.serviceResult == UA_STATUSCODE_BADTOOMANYPUBLISHREQUESTS) {
+ if(client->config.outStandingPublishRequests > 1) {
+ client->config.outStandingPublishRequests--;
+ UA_LOG_WARNING(client->config.logger, UA_LOGCATEGORY_CLIENT,
+ "Too many publishrequest, reduce outStandingPublishRequests to %d",
+ client->config.outStandingPublishRequests);
+ } else {
+ UA_LOG_ERROR(client->config.logger, UA_LOGCATEGORY_CLIENT,
+ "Too many publishrequest when outStandingPublishRequests = 1");
+ UA_Client_Subscriptions_deleteSingle(client, response->subscriptionId);
+ }
+ return;
+ }
+
+ if(response->responseHeader.serviceResult == UA_STATUSCODE_BADSHUTDOWN)
+ return;
+
+ if(!LIST_FIRST(&client->subscriptions)) {
+ response->responseHeader.serviceResult = UA_STATUSCODE_BADNOSUBSCRIPTION;
+ return;
+ }
+
+ if(response->responseHeader.serviceResult == UA_STATUSCODE_BADSESSIONCLOSED) {
+ if(client->state >= UA_CLIENTSTATE_SESSION) {
+ UA_LOG_WARNING(client->config.logger, UA_LOGCATEGORY_CLIENT,
+ "Received Publish Response with code %s",
+ UA_StatusCode_name(response->responseHeader.serviceResult));
+ }
+ return;
+ }
+
+ if(response->responseHeader.serviceResult == UA_STATUSCODE_BADSESSIONIDINVALID) {
+ UA_Client_close(client); /* TODO: This should be handled before the process callback */
+ UA_LOG_WARNING(client->config.logger, UA_LOGCATEGORY_CLIENT,
+ "Received BadSessionIdInvalid");
+ return;
+ }
+
+ if(response->responseHeader.serviceResult != UA_STATUSCODE_GOOD) {
+ UA_LOG_WARNING(client->config.logger, UA_LOGCATEGORY_CLIENT,
+ "Received Publish Response with code %s",
+ UA_StatusCode_name(response->responseHeader.serviceResult));
+ return;
+ }
+
+ UA_Client_Subscription *sub = findSubscription(client, response->subscriptionId);
+ if(!sub) {
+ response->responseHeader.serviceResult = UA_STATUSCODE_BADINTERNALERROR;
+ UA_LOG_WARNING(client->config.logger, UA_LOGCATEGORY_CLIENT,
+ "Received Publish Response for a non-existant subscription");
+ return;
+ }
+
+ sub->lastActivity = UA_DateTime_nowMonotonic();
+
+ /* 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 %u but got %u",
+ 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_close(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. */
+ if (msg->notificationDataSize)
+ sub->sequenceNumber = msg->sequenceNumber;
+
+ /* Process the notification messages */
+ for(size_t k = 0; k < msg->notificationDataSize; ++k)
+ processNotificationMessage(client, sub, &msg->notificationData[k]);
+
+ /* Add to the list of pending acks */
+ for(size_t i = 0; i < response->availableSequenceNumbersSize; i++) {
+ if(response->availableSequenceNumbers[i] != msg->sequenceNumber)
+ continue;
+ UA_Client_NotificationsAckNumber *tmpAck = (UA_Client_NotificationsAckNumber*)
+ UA_malloc(sizeof(UA_Client_NotificationsAckNumber));
+ if(!tmpAck) {
+ UA_LOG_WARNING(client->config.logger, UA_LOGCATEGORY_CLIENT,
+ "Not enough memory to store the acknowledgement for a publish "
+ "message on subscription %u", sub->subscriptionId);
+ break;
+ }
+ tmpAck->subAck.sequenceNumber = msg->sequenceNumber;
+ tmpAck->subAck.subscriptionId = sub->subscriptionId;
+ LIST_INSERT_HEAD(&client->pendingNotificationsAcks, tmpAck, listEntry);
+ break;
+ }
+}
+
+static void
+processPublishResponseAsync(UA_Client *client, void *userdata, UA_UInt32 requestId,
+ void *response, const UA_DataType *responseType) {
+ UA_PublishRequest *req = (UA_PublishRequest*)userdata;
+ UA_PublishResponse *res = (UA_PublishResponse*)response;
+
+ /* Process the response */
+ UA_Client_Subscriptions_processPublishResponse(client, req, res);
+
+ /* Delete the cached request */
+ UA_PublishRequest_delete(req);
+
+ /* Fill up the outstanding publish requests */
+ UA_Client_Subscriptions_backgroundPublish(client);
+}
+
+void
+UA_Client_Subscriptions_clean(UA_Client *client) {
+ UA_Client_NotificationsAckNumber *n, *tmp;
+ LIST_FOREACH_SAFE(n, &client->pendingNotificationsAcks, listEntry, tmp) {
+ LIST_REMOVE(n, listEntry);
+ UA_free(n);
+ }
+
+ UA_Client_Subscription *sub, *tmps;
+ LIST_FOREACH_SAFE(sub, &client->subscriptions, listEntry, tmps)
+ UA_Client_Subscription_deleteInternal(client, sub); /* force local removal */
+
+ client->monitoredItemHandles = 0;
+}
+
+void
+UA_Client_Subscriptions_backgroundPublishInactivityCheck(UA_Client *client) {
+ if(client->state < UA_CLIENTSTATE_SESSION)
+ return;
+
+ /* Is the lack of responses the client's fault? */
+ if(client->currentlyOutStandingPublishRequests == 0)
+ return;
+
+ UA_Client_Subscription *sub;
+ LIST_FOREACH(sub, &client->subscriptions, listEntry) {
+ UA_DateTime maxSilence = (UA_DateTime)
+ ((sub->publishingInterval * sub->maxKeepAliveCount) +
+ client->config.timeout) * UA_DATETIME_MSEC;
+ if(maxSilence + sub->lastActivity < UA_DateTime_nowMonotonic()) {
+ /* Reset activity */
+ sub->lastActivity = UA_DateTime_nowMonotonic();
+
+ if(client->config.subscriptionInactivityCallback)
+ client->config.subscriptionInactivityCallback(client, sub->subscriptionId, sub->context);
+ UA_LOG_ERROR(client->config.logger, UA_LOGCATEGORY_CLIENT,
+ "Inactivity for Subscription %u.", sub->subscriptionId);
+ }
+ }
+}
+
+UA_StatusCode
+UA_Client_Subscriptions_backgroundPublish(UA_Client *client) {
+ if(client->state < UA_CLIENTSTATE_SESSION)
+ return UA_STATUSCODE_BADSERVERNOTCONNECTED;
+
+ /* The session must have at least one subscription */
+ if(!LIST_FIRST(&client->subscriptions))
+ return UA_STATUSCODE_GOOD;
+
+ while(client->currentlyOutStandingPublishRequests < client->config.outStandingPublishRequests) {
+ UA_PublishRequest *request = UA_PublishRequest_new();
+ if (!request)
+ return UA_STATUSCODE_BADOUTOFMEMORY;
+
+ request->requestHeader.timeoutHint=60000;
+ UA_StatusCode retval = UA_Client_preparePublishRequest(client, request);
+ if(retval != UA_STATUSCODE_GOOD) {
+ UA_PublishRequest_delete(request);
+ return retval;
+ }
+
+ UA_UInt32 requestId;
+ client->currentlyOutStandingPublishRequests++;
+
+ /* Disable the timeout, it is treat in UA_Client_Subscriptions_backgroundPublishInactivityCheck */
+ retval = __UA_Client_AsyncServiceEx(client, request, &UA_TYPES[UA_TYPES_PUBLISHREQUEST],
+ processPublishResponseAsync,
+ &UA_TYPES[UA_TYPES_PUBLISHRESPONSE],
+ (void*)request, &requestId, 0);
+ if(retval != UA_STATUSCODE_GOOD) {
+ UA_PublishRequest_delete(request);
+ return retval;
+ }
+ }
+
+ return UA_STATUSCODE_GOOD;
+}
+
+#endif /* UA_ENABLE_SUBSCRIPTIONS */
+
+/*********************************** amalgamated original file "/home/jvoe/open62541/src/client/ua_client_subscriptions_deprecated.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) Julius Pfrommer, Fraunhofer IOSB
+ * Copyright 2015 (c) Oleksiy Vasylyev
+ * Copyright 2016 (c) Sten Grüner
+ * Copyright 2017-2018 (c) Thomas Stalder, Blue Time Concept SA
+ * Copyright 2016-2017 (c) Florian Palm
+ * Copyright 2017 (c) Frank Meerkötter
+ * Copyright 2017 (c) Stefan Profanter, fortiss GmbH
+ */
+
+
+#ifdef UA_ENABLE_SUBSCRIPTIONS /* conditional compilation */
+
+const UA_SubscriptionSettings UA_SubscriptionSettings_default = {
+ 500.0, /* .requestedPublishingInterval */
+ 10000, /* .requestedLifetimeCount */
+ 1, /* .requestedMaxKeepAliveCount */
+ 0, /* .maxNotificationsPerPublish */
+ true, /* .publishingEnabled */
+ 0 /* .priority */
+};
+
+UA_StatusCode
+UA_Client_Subscriptions_new(UA_Client *client, UA_SubscriptionSettings settings,
+ UA_UInt32 *newSubscriptionId) {
+ UA_CreateSubscriptionRequest request;
+ UA_CreateSubscriptionRequest_init(&request);
+ request.requestedPublishingInterval = settings.requestedPublishingInterval;
+ request.requestedLifetimeCount = settings.requestedLifetimeCount;
+ request.requestedMaxKeepAliveCount = settings.requestedMaxKeepAliveCount;
+ request.maxNotificationsPerPublish = settings.maxNotificationsPerPublish;
+ request.publishingEnabled = settings.publishingEnabled;
+ request.priority = settings.priority;
+
+ UA_CreateSubscriptionResponse response =
+ UA_Client_Subscriptions_create(client, request, NULL, NULL, NULL);
+
+ UA_StatusCode retval = response.responseHeader.serviceResult;
+ if(retval == UA_STATUSCODE_GOOD && newSubscriptionId)
+ *newSubscriptionId = response.subscriptionId;
+
+ UA_CreateSubscriptionResponse_deleteMembers(&response);
+ return retval;
+}
+
+UA_StatusCode
+UA_Client_Subscriptions_remove(UA_Client *client, UA_UInt32 subscriptionId) {
+ UA_DeleteSubscriptionsRequest request;
+ UA_DeleteSubscriptionsRequest_init(&request);
+ request.subscriptionIdsSize = 1;
+ request.subscriptionIds = &subscriptionId;
+
+ UA_DeleteSubscriptionsResponse response =
+ UA_Client_Subscriptions_delete(client, request);
+
+ UA_StatusCode retval = response.responseHeader.serviceResult;
+ if(retval == UA_STATUSCODE_GOOD) {
+ if(response.resultsSize != 1)
+ retval = UA_STATUSCODE_BADINTERNALERROR;
+ }
+
+ if(retval == UA_STATUSCODE_GOOD)
+ retval = response.results[0];
+
+ UA_DeleteSubscriptionsResponse_deleteMembers(&response);
+ return retval;
+}
+
+UA_StatusCode
+UA_Client_Subscriptions_manuallySendPublishRequest(UA_Client *client) {
+ if(client->state < UA_CLIENTSTATE_SESSION)
+ return UA_STATUSCODE_BADSERVERNOTCONNECTED;
+
+ UA_StatusCode retval = UA_STATUSCODE_GOOD;
+
+ UA_DateTime now = UA_DateTime_nowMonotonic();
+ UA_DateTime maxDate = now + (UA_DateTime)(client->config.timeout * UA_DATETIME_MSEC);
+
+ UA_Boolean moreNotifications = true;
+ while(moreNotifications) {
+ UA_PublishRequest request;
+ UA_PublishRequest_init(&request);
+ retval = UA_Client_preparePublishRequest(client, &request);
+ if(retval != UA_STATUSCODE_GOOD)
+ return retval;
+
+ /* Manually increase the number of sent publish requests. Otherwise we
+ * send out one too many when we process async responses when we wait
+ * for the correct publish response. The
+ * currentlyOutStandingPublishRequests will be reduced during processing
+ * of the response. */
+ client->currentlyOutStandingPublishRequests++;
+
+ UA_PublishResponse response;
+ __UA_Client_Service(client,
+ &request, &UA_TYPES[UA_TYPES_PUBLISHREQUEST],
+ &response, &UA_TYPES[UA_TYPES_PUBLISHRESPONSE]);
+ UA_Client_Subscriptions_processPublishResponse(client, &request, &response);
+ UA_PublishRequest_deleteMembers(&request);
+
+ now = UA_DateTime_nowMonotonic();
+ if(now > maxDate) {
+ moreNotifications = UA_FALSE;
+ retval = UA_STATUSCODE_GOODNONCRITICALTIMEOUT;
+ } else {
+ moreNotifications = response.moreNotifications;
+ }
+
+ UA_PublishResponse_deleteMembers(&response);
+ UA_PublishRequest_deleteMembers(&request);
+ }
+
+ if(client->state < UA_CLIENTSTATE_SESSION)
+ return UA_STATUSCODE_BADSERVERNOTCONNECTED;
+
+ return retval;
+}
+
+/* Callbacks for the MonitoredItems. The callbacks for the deprecated API are
+ * wrapped. The wrapper is cleaned up upon destruction. */
+
+typedef struct {
+ UA_MonitoredItemHandlingFunction origCallback;
+ void *context;
+} dataChangeCallbackWrapper;
+
+static void
+dataChangeCallback(UA_Client *client, UA_UInt32 subId, void *subContext,
+ UA_UInt32 monId, void *monContext, UA_DataValue *value) {
+ dataChangeCallbackWrapper *wrapper = (dataChangeCallbackWrapper*)monContext;
+ wrapper->origCallback(client, monId, value, wrapper->context);
+}
+
+typedef struct {
+ UA_MonitoredEventHandlingFunction origCallback;
+ void *context;
+} eventCallbackWrapper;
+
+static void
+eventCallback(UA_Client *client, UA_UInt32 subId, void *subContext,
+ UA_UInt32 monId, void *monContext, size_t nEventFields,
+ UA_Variant *eventFields) {
+ eventCallbackWrapper *wrapper = (eventCallbackWrapper*)monContext;
+ wrapper->origCallback(client, monId, nEventFields, eventFields, wrapper->context);
+}
+
+static void
+deleteMonitoredItemCallback(UA_Client *client, UA_UInt32 subId, void *subContext,
+ UA_UInt32 monId, void *monContext) {
+ UA_free(monContext);
+}
+
+static UA_StatusCode
+addMonitoredItems(UA_Client *client, const UA_UInt32 subscriptionId,
+ UA_MonitoredItemCreateRequest *items, size_t itemsSize,
+ UA_MonitoredItemHandlingFunction *hfs, void **hfContexts,
+ UA_StatusCode *itemResults, UA_UInt32 *newMonitoredItemIds) {
+ /* Create array of wrappers and callbacks */
+ UA_STACKARRAY(dataChangeCallbackWrapper*, wrappers, itemsSize);
+ UA_STACKARRAY(UA_Client_DeleteMonitoredItemCallback, deleteCbs, itemsSize);
+ UA_STACKARRAY(UA_Client_DataChangeNotificationCallback, wrapperCbs, itemsSize);
+
+ for(size_t i = 0; i < itemsSize; i++) {
+ wrappers[i] = (dataChangeCallbackWrapper*)UA_malloc(sizeof(dataChangeCallbackWrapper));
+ if(!wrappers[i]) {
+ for(size_t j = 0; j < i; j++)
+ UA_free(wrappers[j]);
+ return UA_STATUSCODE_BADOUTOFMEMORY;
+ }
+ wrappers[i]->origCallback = (UA_MonitoredItemHandlingFunction)(uintptr_t)hfs[i];
+ wrappers[i]->context = hfContexts[i];
+
+ deleteCbs[i] = deleteMonitoredItemCallback;
+ wrapperCbs[i] = dataChangeCallback;
+ }
+
+ /* Prepare the request */
+ UA_CreateMonitoredItemsRequest request;
+ UA_CreateMonitoredItemsRequest_init(&request);
+ request.subscriptionId = subscriptionId;
+ request.itemsToCreateSize = itemsSize;
+ request.itemsToCreate = items;
+
+ /* Process and return */
+ UA_CreateMonitoredItemsResponse response =
+ UA_Client_MonitoredItems_createDataChanges(client, request, (void**)wrappers,
+ wrapperCbs, deleteCbs);
+
+ UA_StatusCode retval = response.responseHeader.serviceResult;
+ if(retval == UA_STATUSCODE_GOOD && response.resultsSize != itemsSize)
+ retval = UA_STATUSCODE_BADINTERNALERROR;
+
+ if(retval == UA_STATUSCODE_GOOD) {
+ for(size_t i = 0; i < itemsSize; i++) {
+ itemResults[i] = response.results[i].statusCode;
+ newMonitoredItemIds[i] = response.results[i].monitoredItemId;
+ }
+ }
+
+ UA_CreateMonitoredItemsResponse_deleteMembers(&response);
+ return retval;
+}
+
+UA_StatusCode
+UA_Client_Subscriptions_addMonitoredItems(UA_Client *client, const UA_UInt32 subscriptionId,
+ UA_MonitoredItemCreateRequest *items, size_t itemsSize,
+ UA_MonitoredItemHandlingFunction *hfs,
+ void **hfContexts, UA_StatusCode *itemResults,
+ UA_UInt32 *newMonitoredItemIds) {
+ return addMonitoredItems(client, subscriptionId, items, itemsSize, hfs, hfContexts, itemResults,
+ newMonitoredItemIds);
+}
+
+UA_StatusCode
+UA_Client_Subscriptions_addMonitoredItem(UA_Client *client, UA_UInt32 subscriptionId,
+ UA_NodeId nodeId, UA_UInt32 attributeID,
+ UA_MonitoredItemHandlingFunction hf, void *hfContext,
+ UA_UInt32 *newMonitoredItemId, UA_Double samplingInterval) {
+ UA_MonitoredItemCreateRequest item;
+ UA_MonitoredItemCreateRequest_init(&item);
+ item.itemToMonitor.nodeId = nodeId;
+ item.itemToMonitor.attributeId = attributeID;
+ item.monitoringMode = UA_MONITORINGMODE_REPORTING;
+ item.requestedParameters.samplingInterval = samplingInterval;
+ item.requestedParameters.discardOldest = true;
+ item.requestedParameters.queueSize = 1;
+
+ UA_StatusCode retval_item = UA_STATUSCODE_GOOD;
+ UA_StatusCode retval =
+ addMonitoredItems(client, subscriptionId, &item, 1,
+ (UA_MonitoredItemHandlingFunction*)(uintptr_t)&hf,
+ &hfContext, &retval_item, newMonitoredItemId);
+ return retval | retval_item;
+}
+
+static UA_StatusCode
+addMonitoredEvents(UA_Client *client, const UA_UInt32 subscriptionId,
+ UA_MonitoredItemCreateRequest *items, size_t itemsSize,
+ UA_MonitoredEventHandlingFunction *hfs,
+ void **hfContexts, UA_StatusCode *itemResults,
+ UA_UInt32 *newMonitoredItemIds) {
+ /* Create array of wrappers and callbacks */
+ UA_STACKARRAY(eventCallbackWrapper*, wrappers, itemsSize);
+ UA_STACKARRAY(UA_Client_DeleteMonitoredItemCallback, deleteCbs, itemsSize);
+ UA_STACKARRAY(UA_Client_EventNotificationCallback, wrapperCbs, itemsSize);
+
+ for(size_t i = 0; i < itemsSize; i++) {
+ wrappers[i] = (eventCallbackWrapper*)UA_malloc(sizeof(eventCallbackWrapper));
+ if(!wrappers[i]) {
+ for(size_t j = 0; j < i; j++)
+ UA_free(wrappers[j]);
+ return UA_STATUSCODE_BADOUTOFMEMORY;
+ }
+ wrappers[i]->origCallback = (UA_MonitoredEventHandlingFunction)(uintptr_t)hfs[i];
+ wrappers[i]->context = hfContexts[i];
+
+ deleteCbs[i] = deleteMonitoredItemCallback;
+ wrapperCbs[i] = eventCallback;
+ }
+
+ /* Prepare the request */
+ UA_CreateMonitoredItemsRequest request;
+ UA_CreateMonitoredItemsRequest_init(&request);
+ request.subscriptionId = subscriptionId;
+ request.itemsToCreateSize = itemsSize;
+ request.itemsToCreate = items;
+
+ /* Process and return */
+ UA_CreateMonitoredItemsResponse response =
+ UA_Client_MonitoredItems_createEvents(client, request, (void**)wrappers,
+ wrapperCbs, deleteCbs);
+
+ UA_StatusCode retval = response.responseHeader.serviceResult;
+ if(retval == UA_STATUSCODE_GOOD && response.resultsSize != itemsSize)
+ retval = UA_STATUSCODE_BADINTERNALERROR;
+
+ if(retval == UA_STATUSCODE_GOOD) {
+ for(size_t i = 0; i < itemsSize; i++)
+ itemResults[i] = response.results[i].statusCode;
+ }
+
+ UA_CreateMonitoredItemsResponse_deleteMembers(&response);
+ return retval;
+}
+
+UA_StatusCode
+UA_Client_Subscriptions_addMonitoredEvents(UA_Client *client, const UA_UInt32 subscriptionId,
+ UA_MonitoredItemCreateRequest *items, size_t itemsSize,
+ UA_MonitoredEventHandlingFunction *hfs,
+ void **hfContexts, UA_StatusCode *itemResults,
+ UA_UInt32 *newMonitoredItemIds) {
+ return addMonitoredEvents(client, subscriptionId, items, itemsSize, hfs,
+ hfContexts, itemResults, newMonitoredItemIds);
+}
+
+UA_StatusCode
+UA_Client_Subscriptions_addMonitoredEvent(UA_Client *client, UA_UInt32 subscriptionId,
+ const UA_NodeId nodeId, UA_UInt32 attributeID,
+ const UA_SimpleAttributeOperand *selectClauses,
+ size_t selectClausesSize,
+ const UA_ContentFilterElement *whereClauses,
+ size_t whereClausesSize,
+ const UA_MonitoredEventHandlingFunction hf,
+ void *hfContext, UA_UInt32 *newMonitoredItemId) {
+ UA_MonitoredItemCreateRequest item;
+ UA_MonitoredItemCreateRequest_init(&item);
+ item.itemToMonitor.nodeId = nodeId;
+ item.itemToMonitor.attributeId = attributeID;
+ item.monitoringMode = UA_MONITORINGMODE_REPORTING;
+ item.requestedParameters.samplingInterval = 0;
+ item.requestedParameters.discardOldest = false;
+
+ UA_EventFilter *evFilter = UA_EventFilter_new();
+ if(!evFilter)
+ return UA_STATUSCODE_BADOUTOFMEMORY;
+ UA_EventFilter_init(evFilter);
+ evFilter->selectClausesSize = selectClausesSize;
+ evFilter->selectClauses = (UA_SimpleAttributeOperand*)(uintptr_t)selectClauses;
+ evFilter->whereClause.elementsSize = whereClausesSize;
+ evFilter->whereClause.elements = (UA_ContentFilterElement*)(uintptr_t)whereClauses;
+
+ item.requestedParameters.filter.encoding = UA_EXTENSIONOBJECT_DECODED_NODELETE;
+ item.requestedParameters.filter.content.decoded.type = &UA_TYPES[UA_TYPES_EVENTFILTER];
+ item.requestedParameters.filter.content.decoded.data = evFilter;
+ UA_StatusCode retval_item = UA_STATUSCODE_GOOD;
+ UA_StatusCode retval = addMonitoredEvents(client, subscriptionId, &item, 1,
+ (UA_MonitoredEventHandlingFunction*)(uintptr_t)&hf,
+ &hfContext, &retval_item, newMonitoredItemId);
+ UA_free(evFilter);
+ return retval | retval_item;
+}
+
+static UA_StatusCode
+removeMonitoredItems(UA_Client *client, UA_UInt32 subscriptionId,
+ UA_UInt32 *monitoredItemIds, size_t itemsSize,
+ UA_StatusCode *itemResults) {
+ UA_DeleteMonitoredItemsRequest request;
+ UA_DeleteMonitoredItemsRequest_init(&request);
+ request.subscriptionId = subscriptionId;
+ request.monitoredItemIdsSize = itemsSize;
+ request.monitoredItemIds = monitoredItemIds;
+
+ UA_DeleteMonitoredItemsResponse response = UA_Client_MonitoredItems_delete(client, request);
+ UA_StatusCode retval = response.responseHeader.serviceResult;
+ if(retval == UA_STATUSCODE_GOOD) {
+ if(response.resultsSize != itemsSize) {
+ retval = UA_STATUSCODE_BADINTERNALERROR;
+ } else {
+ for(size_t i = 0; i < itemsSize; i++)
+ itemResults[i] = response.results[i];
+ }
+ }
+ UA_DeleteMonitoredItemsResponse_deleteMembers(&response);
+ return retval;
+}
+
+UA_StatusCode
+UA_Client_Subscriptions_removeMonitoredItems(UA_Client *client, UA_UInt32 subscriptionId,
+ UA_UInt32 *monitoredItemIds, size_t itemsSize,
+ UA_StatusCode *itemResults) {
+ return removeMonitoredItems(client, subscriptionId, monitoredItemIds, itemsSize, itemResults);
+}
+
+UA_StatusCode
+UA_Client_Subscriptions_removeMonitoredItem(UA_Client *client, UA_UInt32 subscriptionId,
+ UA_UInt32 monitoredItemId) {
+ UA_StatusCode retval_item = UA_STATUSCODE_GOOD;
+ UA_StatusCode retval = removeMonitoredItems(client, subscriptionId, &monitoredItemId, 1, &retval_item);
+ return retval | retval_item;
+}
+
+#endif /* UA_ENABLE_SUBSCRIPTIONS */
+
+/*********************************** amalgamated original file "/home/jvoe/open62541/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 */
+
+#include <limits.h>
+
+/* 2000-03-01 (mod 400 year, immediately after feb29 */
+#define LEAPOCH (946684800LL + 86400*(31+29))
+
+#define DAYS_PER_400Y (365*400 + 97)
+#define DAYS_PER_100Y (365*100 + 24)
+#define DAYS_PER_4Y (365*4 + 1)
+
+int __secs_to_tm(long long t, struct mytm *tm) {
+ long long days, secs, years;
+ int remdays, remsecs, remyears;
+ int qc_cycles, c_cycles, q_cycles;
+ int months;
+ int wday, yday, leap;
+ static const char days_in_month[] = {31,30,31,30,31,31,30,31,30,31,31,29};
+
+ /* Reject time_t values whose year would overflow int */
+ if (t < INT_MIN * 31622400LL || t > INT_MAX * 31622400LL)
+ return -1;
+
+ secs = t - LEAPOCH;
+ days = secs / 86400LL;
+ remsecs = (int)(secs % 86400);
+ if (remsecs < 0) {
+ remsecs += 86400;
+ --days;
+ }
+
+ wday = (int)((3+days)%7);
+ if (wday < 0) wday += 7;
+
+ qc_cycles = (int)(days / DAYS_PER_400Y);
+ remdays = (int)(days % DAYS_PER_400Y);
+ if (remdays < 0) {
+ remdays += DAYS_PER_400Y;
+ --qc_cycles;
+ }
+
+ c_cycles = remdays / DAYS_PER_100Y;
+ if (c_cycles == 4) --c_cycles;
+ remdays -= c_cycles * DAYS_PER_100Y;
+
+ q_cycles = remdays / DAYS_PER_4Y;
+ if (q_cycles == 25) --q_cycles;
+ remdays -= q_cycles * DAYS_PER_4Y;
+
+ remyears = remdays / 365;
+ if (remyears == 4) --remyears;
+ remdays -= remyears * 365;
+
+ leap = !remyears && (q_cycles || !c_cycles);
+ yday = remdays + 31 + 28 + leap;
+ if (yday >= 365+leap) yday -= 365+leap;
+
+ years = remyears + 4*q_cycles + 100*c_cycles + 400LL*qc_cycles;
+
+ for (months=0; days_in_month[months] <= remdays; ++months)
+ remdays -= days_in_month[months];
+
+ if (years+100 > INT_MAX || years+100 < INT_MIN)
+ return -1;
+
+ tm->tm_year = (int)(years + 100);
+ tm->tm_mon = months + 2;
+ if (tm->tm_mon >= 12) {
+ tm->tm_mon -=12;
+ ++tm->tm_year;
+ }
+ tm->tm_mday = remdays + 1;
+ tm->tm_wday = wday;
+ tm->tm_yday = yday;
+
+ tm->tm_hour = remsecs / 3600;
+ tm->tm_min = remsecs / 60 % 60;
+ tm->tm_sec = remsecs % 60;
+
+ return 0;
+}
+
+/*********************************** amalgamated original file "/home/jvoe/open62541/deps/pcg_basic.c" ***********************************/
+
+/*
+ * PCG Random Number Generation for C.
+ *
+ * Copyright 2014 Melissa O'Neill <oneill@pcg-random.org>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * For additional information about the PCG random number generation scheme,
+ * including its license and other licensing options, visit
+ *
+ * http://www.pcg-random.org
+ */
+
+
+void pcg32_srandom_r(pcg32_random_t* rng, uint64_t initial_state, uint64_t initseq) {
+ rng->state = 0U;
+ rng->inc = (initseq << 1u) | 1u;
+ pcg32_random_r(rng);
+ rng->state += initial_state;
+ pcg32_random_r(rng);
+}
+
+uint32_t pcg32_random_r(pcg32_random_t* rng) {
+ uint64_t oldstate = rng->state;
+ rng->state = oldstate * 6364136223846793005ULL + rng->inc;
+ uint32_t xorshifted = (uint32_t)(((oldstate >> 18u) ^ oldstate) >> 27u);
+ uint32_t rot = (uint32_t)(oldstate >> 59u);
+ return (xorshifted >> rot) | (xorshifted << ((~rot + 1u) & 31)); /* was (xorshifted >> rot) | (xorshifted << ((-rot) & 31)) */
+}
+
+/*********************************** amalgamated original file "/home/jvoe/open62541/plugins/ua_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.
+ *
+ * Copyright 2016-2017 (c) Julius Pfrommer, Fraunhofer IOSB
+ * Copyright 2016-2017 (c) Stefan Profanter, fortiss GmbH
+ * Copyright 2017 (c) frax2222
+ * Copyright 2017 (c) Jose Cabral
+ * Copyright 2017 (c) Thomas Stalder, Blue Time Concept SA
+ */
+
+/* Enable POSIX features */
+#if !defined(_XOPEN_SOURCE) && !defined(_WRS_KERNEL)
+# define _XOPEN_SOURCE 600
+#endif
+#ifndef _DEFAULT_SOURCE
+# define _DEFAULT_SOURCE
+#endif
+/* On older systems we need to define _BSD_SOURCE.
+ * _DEFAULT_SOURCE is an alias for that. */
+#ifndef _BSD_SOURCE
+# define _BSD_SOURCE
+#endif
+
+/* Disable some security warnings on MSVC */
+#ifdef _MSC_VER
+# define _CRT_SECURE_NO_WARNINGS
+#endif
+
+/* Assume that Windows versions are newer than Windows XP */
+#if defined(__MINGW32__) && (!defined(WINVER) || WINVER < 0x501)
+# undef WINVER
+# undef _WIN32_WINDOWS
+# undef _WIN32_WINNT
+# define WINVER 0x0501
+# define _WIN32_WINDOWS 0x0501
+# define _WIN32_WINNT 0x0501
+#endif
+
+
+#include <stdio.h> // snprintf
+#include <string.h> // memset
+
+#if !defined(UA_FREERTOS)
+# include <errno.h>
+#else
+# define AI_PASSIVE 0x01
+# define TRUE 1
+# define FALSE 0
+# define ioctl ioctlsocket
+#endif
+
+#ifdef _WIN32
+# include <winsock2.h>
+# include <ws2tcpip.h>
+# define CLOSESOCKET(S) closesocket((SOCKET)S)
+# define ssize_t int
+# define WIN32_INT (int)
+# define OPTVAL_TYPE char
+# define ERR_CONNECTION_PROGRESS WSAEWOULDBLOCK
+# define UA_sleep_ms(X) Sleep(X)
+#else /* _WIN32 */
+# if defined(UA_FREERTOS)
+# define UA_FREERTOS_HOSTNAME "10.200.4.114"
+static inline int gethostname_freertos(char* name, size_t len){
+ if(strlen(UA_FREERTOS_HOSTNAME) > (len))
+ return -1;
+ strcpy(name, UA_FREERTOS_HOSTNAME);
+ return 0;
+}
+#define gethostname gethostname_freertos
+# include <lwip/tcpip.h>
+# include <lwip/netdb.h>
+# define CLOSESOCKET(S) lwip_close(S)
+# define sockaddr_storage sockaddr
+# ifdef BYTE_ORDER
+# undef BYTE_ORDER
+# endif
+# define UA_sleep_ms(X) vTaskDelay(pdMS_TO_TICKS(X))
+# else /* Not freeRTOS */
+# define CLOSESOCKET(S) close(S)
+# include <arpa/inet.h>
+# include <netinet/in.h>
+# include <netdb.h>
+# include <sys/ioctl.h>
+# if defined(_WRS_KERNEL)
+# include <hostLib.h>
+# include <selectLib.h>
+# define UA_sleep_ms(X) \
+ { \
+ struct timespec timeToSleep; \
+ timeToSleep.tv_sec = X / 1000; \
+ timeToSleep.tv_nsec = 1000000 * (X % 1000); \
+ nanosleep(&timeToSleep, NULL); \
+ }
+# else /* defined(_WRS_KERNEL) */
+# include <sys/select.h>
+# define UA_sleep_ms(X) usleep(X * 1000)
+# endif /* defined(_WRS_KERNEL) */
+# endif /* Not freeRTOS */
+
+# define SOCKET int
+# define WIN32_INT
+# define OPTVAL_TYPE int
+# define ERR_CONNECTION_PROGRESS EINPROGRESS
+
+
+# include <fcntl.h>
+# include <unistd.h> // read, write, close
+
+# ifdef __QNX__
+# include <sys/socket.h>
+# endif
+# if defined(__unix__) || (defined(__APPLE__) && defined(__MACH__))
+# include <sys/param.h>
+# if defined(BSD)
+# include<sys/socket.h>
+# endif
+# endif
+# if !defined(__CYGWIN__) && !defined(UA_FREERTOS)
+# include <netinet/tcp.h>
+# endif
+#endif /* _WIN32 */
+
+/* unsigned int for windows and workaround to a glibc bug */
+/* Additionally if GNU_LIBRARY is not defined, it may be using
+ * musl libc (e.g. Docker Alpine) */
+#if defined(_WIN32) || defined(__OpenBSD__) || \
+ (defined(__GNU_LIBRARY__) && (__GNU_LIBRARY__ <= 6) && \
+ (__GLIBC__ <= 2) && (__GLIBC_MINOR__ < 16) || \
+ !defined(__GNU_LIBRARY__))
+# define UA_fd_set(fd, fds) FD_SET((unsigned int)fd, fds)
+# define UA_fd_isset(fd, fds) FD_ISSET((unsigned int)fd, fds)
+#else
+# define UA_fd_set(fd, fds) FD_SET(fd, fds)
+# define UA_fd_isset(fd, fds) FD_ISSET(fd, fds)
+#endif
+
+#ifdef UNDER_CE
+# define errno WSAGetLastError()
+#endif
+
+#ifdef _WIN32
+# define errno__ WSAGetLastError()
+# define INTERRUPTED WSAEINTR
+# define WOULDBLOCK WSAEWOULDBLOCK
+# define AGAIN WSAEWOULDBLOCK
+#else
+# define errno__ errno
+# define INTERRUPTED EINTR
+# define WOULDBLOCK EWOULDBLOCK
+# define AGAIN EAGAIN
+#endif
+
+
+/****************************/
+/* Generic Socket Functions */
+/****************************/
+
+static UA_StatusCode
+connection_getsendbuffer(UA_Connection *connection,
+ size_t length, UA_ByteString *buf) {
+ if(length > connection->remoteConf.recvBufferSize)
+ return UA_STATUSCODE_BADCOMMUNICATIONERROR;
+ return UA_ByteString_allocBuffer(buf, length);
+}
+
+static void
+connection_releasesendbuffer(UA_Connection *connection,
+ UA_ByteString *buf) {
+ UA_ByteString_deleteMembers(buf);
+}
+
+static void
+connection_releaserecvbuffer(UA_Connection *connection,
+ UA_ByteString *buf) {
+ UA_ByteString_deleteMembers(buf);
+}
+
+static UA_StatusCode
+connection_write(UA_Connection *connection, UA_ByteString *buf) {
+ if(connection->state == UA_CONNECTION_CLOSED) {
+ UA_ByteString_deleteMembers(buf);
+ return UA_STATUSCODE_BADCONNECTIONCLOSED;
+ }
+
+ /* Prevent OS signals when sending to a closed socket */
+ int flags = 0;
+#ifdef MSG_NOSIGNAL
+ flags |= MSG_NOSIGNAL;
+#endif
+
+ /* Send the full buffer. This may require several calls to send */
+ size_t nWritten = 0;
+ do {
+ ssize_t n = 0;
+ do {
+ size_t bytes_to_send = buf->length - nWritten;
+ n = send((SOCKET)connection->sockfd,
+ (const char*)buf->data + nWritten,
+ WIN32_INT bytes_to_send, flags);
+ if(n < 0 && errno__ != INTERRUPTED && errno__ != AGAIN) {
+ connection->close(connection);
+ UA_ByteString_deleteMembers(buf);
+ return UA_STATUSCODE_BADCONNECTIONCLOSED;
+ }
+ } while(n < 0);
+ nWritten += (size_t)n;
+ } while(nWritten < buf->length);
+
+ /* Free the buffer */
+ UA_ByteString_deleteMembers(buf);
+ return UA_STATUSCODE_GOOD;
+}
+
+static UA_StatusCode
+connection_recv(UA_Connection *connection, UA_ByteString *response,
+ UA_UInt32 timeout) {
+ if(connection->state == UA_CONNECTION_CLOSED)
+ return UA_STATUSCODE_BADCONNECTIONCLOSED;
+
+ /* Listen on the socket for the given timeout until a message arrives */
+ if(timeout > 0) {
+ fd_set fdset;
+ FD_ZERO(&fdset);
+ UA_fd_set(connection->sockfd, &fdset);
+ UA_UInt32 timeout_usec = timeout * 1000;
+ struct timeval tmptv = {(long int)(timeout_usec / 1000000),
+ (long int)(timeout_usec % 1000000)};
+ int resultsize = select(connection->sockfd+1, &fdset, NULL,
+ NULL, &tmptv);
+
+ /* No result */
+ if(resultsize == 0)
+ return UA_STATUSCODE_GOODNONCRITICALTIMEOUT;
+
+ if(resultsize == -1) {
+ /* The call to select was interrupted manually. Act as if it timed
+ * out */
+ if(errno == EINTR)
+ return UA_STATUSCODE_GOODNONCRITICALTIMEOUT;
+
+ /* The error cannot be recovered. Close the connection. */
+ connection->close(connection);
+ return UA_STATUSCODE_BADCONNECTIONCLOSED;
+ }
+ }
+
+ response->data = (UA_Byte*)
+ UA_malloc(connection->localConf.recvBufferSize);
+ if(!response->data) {
+ response->length = 0;
+ return UA_STATUSCODE_BADOUTOFMEMORY; /* not enough memory retry */
+ }
+
+ /* Get the received packet(s) */
+ ssize_t ret = recv(connection->sockfd, (char*)response->data,
+ connection->localConf.recvBufferSize, 0);
+
+ /* The remote side closed the connection */
+ if(ret == 0) {
+ UA_ByteString_deleteMembers(response);
+ connection->close(connection);
+ return UA_STATUSCODE_BADCONNECTIONCLOSED;
+ }
+
+ /* Error case */
+ if(ret < 0) {
+ UA_ByteString_deleteMembers(response);
+ if(errno__ == INTERRUPTED || (timeout > 0) ?
+ false : (errno__ == EAGAIN || errno__ == WOULDBLOCK))
+ return UA_STATUSCODE_GOOD; /* statuscode_good but no data -> retry */
+ connection->close(connection);
+ return UA_STATUSCODE_BADCONNECTIONCLOSED;
+ }
+
+ /* Set the length of the received buffer */
+ response->length = (size_t)ret;
+ return UA_STATUSCODE_GOOD;
+}
+
+static UA_StatusCode
+socket_set_nonblocking(SOCKET sockfd) {
+#ifdef _WIN32
+ u_long iMode = 1;
+ if(ioctlsocket(sockfd, FIONBIO, &iMode) != NO_ERROR)
+ return UA_STATUSCODE_BADINTERNALERROR;
+#elif defined(_WRS_KERNEL) || defined(UA_FREERTOS)
+ int on = TRUE;
+ if(ioctl(sockfd, FIONBIO, &on) < 0)
+ return UA_STATUSCODE_BADINTERNALERROR;
+#else
+ int opts = fcntl(sockfd, F_GETFL);
+ if(opts < 0 || fcntl(sockfd, F_SETFL, opts|O_NONBLOCK) < 0)
+ return UA_STATUSCODE_BADINTERNALERROR;
+#endif
+ return UA_STATUSCODE_GOOD;
+}
+
+static UA_StatusCode
+socket_set_blocking(SOCKET sockfd) {
+#ifdef _WIN32
+ u_long iMode = 0;
+ if(ioctlsocket(sockfd, FIONBIO, &iMode) != NO_ERROR)
+ return UA_STATUSCODE_BADINTERNALERROR;
+#elif defined(_WRS_KERNEL) || defined(UA_FREERTOS)
+ int on = FALSE;
+ if(ioctl(sockfd, FIONBIO, &on) < 0)
+ return UA_STATUSCODE_BADINTERNALERROR;
+#else
+ int opts = fcntl(sockfd, F_GETFL);
+ if(opts < 0 || fcntl(sockfd, F_SETFL, opts & (~O_NONBLOCK)) < 0)
+ return UA_STATUSCODE_BADINTERNALERROR;
+#endif
+ return UA_STATUSCODE_GOOD;
+}
+
+/***************************/
+/* Server NetworkLayer TCP */
+/***************************/
+
+#define MAXBACKLOG 100
+#define NOHELLOTIMEOUT 120000 /* timeout in ms before close the connection
+ * if server does not receive Hello Message */
+
+typedef struct ConnectionEntry {
+ UA_Connection connection;
+ LIST_ENTRY(ConnectionEntry) pointers;
+} ConnectionEntry;
+
+typedef struct {
+ UA_Logger logger;
+ UA_ConnectionConfig conf;
+ UA_UInt16 port;
+ UA_Int32 serverSockets[FD_SETSIZE];
+ UA_UInt16 serverSocketsSize;
+ LIST_HEAD(, ConnectionEntry) connections;
+} ServerNetworkLayerTCP;
+
+static void
+ServerNetworkLayerTCP_freeConnection(UA_Connection *connection) {
+ UA_Connection_deleteMembers(connection);
+ UA_free(connection);
+}
+
+/* This performs only 'shutdown'. 'close' is called when the shutdown
+ * socket is returned from select. */
+static void
+ServerNetworkLayerTCP_close(UA_Connection *connection) {
+ if (connection->state == UA_CONNECTION_CLOSED)
+ return;
+ shutdown((SOCKET)connection->sockfd, 2);
+ connection->state = UA_CONNECTION_CLOSED;
+}
+
+static UA_StatusCode
+ServerNetworkLayerTCP_add(ServerNetworkLayerTCP *layer, UA_Int32 newsockfd,
+ struct sockaddr_storage *remote) {
+ /* Set nonblocking */
+ socket_set_nonblocking(newsockfd);
+
+ /* Do not merge packets on the socket (disable Nagle's algorithm) */
+ int dummy = 1;
+ if(setsockopt(newsockfd, IPPROTO_TCP, TCP_NODELAY,
+ (const char *)&dummy, sizeof(dummy)) < 0) {
+ UA_LOG_SOCKET_ERRNO_WRAP(
+ UA_LOG_ERROR(layer->logger, UA_LOGCATEGORY_NETWORK,
+ "Cannot set socket option TCP_NODELAY. Error: %s",
+ errno_str));
+ return UA_STATUSCODE_BADUNEXPECTEDERROR;
+ }
+
+#if !defined(UA_FREERTOS)
+ /* Get the peer name for logging */
+ char remote_name[100];
+ int res = getnameinfo((struct sockaddr*)remote,
+ sizeof(struct sockaddr_storage),
+ remote_name, sizeof(remote_name),
+ NULL, 0, NI_NUMERICHOST);
+ if(res == 0) {
+ UA_LOG_INFO(layer->logger, UA_LOGCATEGORY_NETWORK,
+ "Connection %i | New connection over TCP from %s",
+ (int)newsockfd, remote_name);
+ } else {
+ UA_LOG_SOCKET_ERRNO_WRAP(UA_LOG_WARNING(layer->logger, UA_LOGCATEGORY_NETWORK,
+ "Connection %i | New connection over TCP, "
+ "getnameinfo failed with error: %s",
+ (int)newsockfd, errno_str));
+ }
+#endif
+ /* Allocate and initialize the connection */
+ ConnectionEntry *e = (ConnectionEntry*)UA_malloc(sizeof(ConnectionEntry));
+ if(!e){
+ CLOSESOCKET(newsockfd);
+ return UA_STATUSCODE_BADOUTOFMEMORY;
+ }
+
+ UA_Connection *c = &e->connection;
+ memset(c, 0, sizeof(UA_Connection));
+ c->sockfd = newsockfd;
+ c->handle = layer;
+ c->localConf = layer->conf;
+ c->remoteConf = layer->conf;
+ c->send = connection_write;
+ c->close = ServerNetworkLayerTCP_close;
+ c->free = ServerNetworkLayerTCP_freeConnection;
+ c->getSendBuffer = connection_getsendbuffer;
+ c->releaseSendBuffer = connection_releasesendbuffer;
+ c->releaseRecvBuffer = connection_releaserecvbuffer;
+ c->state = UA_CONNECTION_OPENING;
+ c->openingDate = UA_DateTime_nowMonotonic();
+
+ /* Add to the linked list */
+ LIST_INSERT_HEAD(&layer->connections, e, pointers);
+ return UA_STATUSCODE_GOOD;
+}
+
+static void
+addServerSocket(ServerNetworkLayerTCP *layer, struct addrinfo *ai) {
+ /* Create the server socket */
+ SOCKET newsock = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
+#ifdef _WIN32
+ if(newsock == INVALID_SOCKET)
+#else
+ if(newsock < 0)
+#endif
+ {
+ UA_LOG_WARNING(layer->logger, UA_LOGCATEGORY_NETWORK,
+ "Error opening the server socket");
+ return;
+ }
+
+ /* Some Linux distributions have net.ipv6.bindv6only not activated. So
+ * sockets can double-bind to IPv4 and IPv6. This leads to problems. Use
+ * AF_INET6 sockets only for IPv6. */
+
+ int optval = 1;
+#if !defined(UA_FREERTOS)
+ if(ai->ai_family == AF_INET6 &&
+ setsockopt(newsock, IPPROTO_IPV6, IPV6_V6ONLY,
+ (const char*)&optval, sizeof(optval)) == -1) {
+ UA_LOG_WARNING(layer->logger, UA_LOGCATEGORY_NETWORK,
+ "Could not set an IPv6 socket to IPv6 only");
+ CLOSESOCKET(newsock);
+ return;
+ }
+#endif
+ if(setsockopt(newsock, SOL_SOCKET, SO_REUSEADDR,
+ (const char *)&optval, sizeof(optval)) == -1) {
+ UA_LOG_WARNING(layer->logger, UA_LOGCATEGORY_NETWORK,
+ "Could not make the socket reusable");
+ CLOSESOCKET(newsock);
+ return;
+ }
+
+
+ if(socket_set_nonblocking(newsock) != UA_STATUSCODE_GOOD) {
+ UA_LOG_WARNING(layer->logger, UA_LOGCATEGORY_NETWORK,
+ "Could not set the server socket to nonblocking");
+ CLOSESOCKET(newsock);
+ return;
+ }
+
+ /* Bind socket to address */
+ if(bind(newsock, ai->ai_addr, WIN32_INT ai->ai_addrlen) < 0) {
+ UA_LOG_SOCKET_ERRNO_WRAP(
+ UA_LOG_WARNING(layer->logger, UA_LOGCATEGORY_NETWORK,
+ "Error binding a server socket: %s", errno_str));
+ CLOSESOCKET(newsock);
+ return;
+ }
+
+ /* Start listening */
+ if(listen(newsock, MAXBACKLOG) < 0) {
+ UA_LOG_SOCKET_ERRNO_WRAP(
+ UA_LOG_WARNING(layer->logger, UA_LOGCATEGORY_NETWORK,
+ "Error listening on server socket: %s", errno_str));
+ CLOSESOCKET(newsock);
+ return;
+ }
+
+ layer->serverSockets[layer->serverSocketsSize] = (UA_Int32)newsock;
+ layer->serverSocketsSize++;
+}
+
+static UA_StatusCode
+ServerNetworkLayerTCP_start(UA_ServerNetworkLayer *nl, const UA_String *customHostname) {
+#ifdef _WIN32
+ WORD wVersionRequested = MAKEWORD(2, 2);
+ WSADATA wsaData;
+ WSAStartup(wVersionRequested, &wsaData);
+#endif
+
+ ServerNetworkLayerTCP *layer = (ServerNetworkLayerTCP *)nl->handle;
+
+ /* Get the discovery url from the hostname */
+ UA_String du = UA_STRING_NULL;
+ if (customHostname->length) {
+ char discoveryUrl[256];
+#ifndef _MSC_VER
+ du.length = (size_t)snprintf(discoveryUrl, 255, "opc.tcp://%.*s:%d/",
+ (int)customHostname->length,
+ customHostname->data,
+ layer->port);
+#else
+ du.length = (size_t)_snprintf_s(discoveryUrl, 255, _TRUNCATE,
+ "opc.tcp://%.*s:%d/",
+ (int)customHostname->length,
+ customHostname->data,
+ layer->port);
+#endif
+ du.data = (UA_Byte*)discoveryUrl;
+ }else{
+ char hostname[256];
+ if(gethostname(hostname, 255) == 0) {
+ char discoveryUrl[256];
+#ifndef _MSC_VER
+ du.length = (size_t)snprintf(discoveryUrl, 255, "opc.tcp://%s:%d/",
+ hostname, layer->port);
+#else
+ du.length = (size_t)_snprintf_s(discoveryUrl, 255, _TRUNCATE,
+ "opc.tcp://%s:%d/", hostname,
+ layer->port);
+#endif
+ du.data = (UA_Byte*)discoveryUrl;
+ }
+ }
+ UA_String_copy(&du, &nl->discoveryUrl);
+
+ /* Get addrinfo of the server and create server sockets */
+ char portno[6];
+#ifndef _MSC_VER
+ snprintf(portno, 6, "%d", layer->port);
+#else
+ _snprintf_s(portno, 6, _TRUNCATE, "%d", layer->port);
+#endif
+ struct addrinfo hints, *res;
+ memset(&hints, 0, sizeof hints);
+ hints.ai_family = AF_UNSPEC;
+ hints.ai_socktype = SOCK_STREAM;
+ hints.ai_flags = AI_PASSIVE;
+#if defined(UA_FREERTOS)
+ hints.ai_protocol = IPPROTO_TCP;
+ char hostname[] = UA_FREERTOS_HOSTNAME;
+ if(getaddrinfo(hostname, portno, &hints, &res) != 0)
+#else
+ if(getaddrinfo(NULL, portno, &hints, &res) != 0)
+#endif
+ return UA_STATUSCODE_BADINTERNALERROR;
+
+ /* There might be serveral addrinfos (for different network cards,
+ * IPv4/IPv6). Add a server socket for all of them. */
+ struct addrinfo *ai = res;
+ for(layer->serverSocketsSize = 0;
+ layer->serverSocketsSize < FD_SETSIZE && ai != NULL;
+ ai = ai->ai_next)
+ addServerSocket(layer, ai);
+ freeaddrinfo(res);
+
+ UA_LOG_INFO(layer->logger, UA_LOGCATEGORY_NETWORK,
+ "TCP network layer listening on %.*s",
+ (int)nl->discoveryUrl.length, nl->discoveryUrl.data);
+ return UA_STATUSCODE_GOOD;
+}
+
+/* After every select, reset the sockets to listen on */
+static UA_Int32
+setFDSet(ServerNetworkLayerTCP *layer, fd_set *fdset) {
+ FD_ZERO(fdset);
+ UA_Int32 highestfd = 0;
+ for(UA_UInt16 i = 0; i < layer->serverSocketsSize; i++) {
+ UA_fd_set(layer->serverSockets[i], fdset);
+ if(layer->serverSockets[i] > highestfd)
+ highestfd = layer->serverSockets[i];
+ }
+
+ ConnectionEntry *e;
+ LIST_FOREACH(e, &layer->connections, pointers) {
+ UA_fd_set(e->connection.sockfd, fdset);
+ if(e->connection.sockfd > highestfd)
+ highestfd = e->connection.sockfd;
+ }
+
+ return highestfd;
+}
+
+static UA_StatusCode
+ServerNetworkLayerTCP_listen(UA_ServerNetworkLayer *nl, UA_Server *server,
+ UA_UInt16 timeout) {
+ /* Every open socket can generate two jobs */
+ ServerNetworkLayerTCP *layer = (ServerNetworkLayerTCP *)nl->handle;
+
+ if (layer->serverSocketsSize == 0)
+ return UA_STATUSCODE_GOOD;
+
+ /* Listen on open sockets (including the server) */
+ fd_set fdset, errset;
+ UA_Int32 highestfd = setFDSet(layer, &fdset);
+ setFDSet(layer, &errset);
+ struct timeval tmptv = {0, timeout * 1000};
+ if (select(highestfd+1, &fdset, NULL, &errset, &tmptv) < 0) {
+ UA_LOG_SOCKET_ERRNO_WRAP(
+ UA_LOG_WARNING(layer->logger, UA_LOGCATEGORY_NETWORK,
+ "Socket select failed with %s", errno_str));
+ // we will retry, so do not return bad
+ return UA_STATUSCODE_GOOD;
+ }
+
+ /* Accept new connections via the server sockets */
+ for(UA_UInt16 i = 0; i < layer->serverSocketsSize; i++) {
+ if(!UA_fd_isset(layer->serverSockets[i], &fdset))
+ continue;
+
+ struct sockaddr_storage remote;
+ socklen_t remote_size = sizeof(remote);
+ SOCKET newsockfd = accept((SOCKET)layer->serverSockets[i],
+ (struct sockaddr*)&remote, &remote_size);
+#ifdef _WIN32
+ if(newsockfd == INVALID_SOCKET)
+#else
+ if(newsockfd < 0)
+#endif
+ continue;
+
+ UA_LOG_TRACE(layer->logger, UA_LOGCATEGORY_NETWORK,
+ "Connection %i | New TCP connection on server socket %i",
+ (int)newsockfd, layer->serverSockets[i]);
+
+ ServerNetworkLayerTCP_add(layer, (UA_Int32)newsockfd, &remote);
+ }
+
+ /* Read from established sockets */
+ ConnectionEntry *e, *e_tmp;
+ UA_DateTime now = UA_DateTime_nowMonotonic();
+ LIST_FOREACH_SAFE(e, &layer->connections, pointers, e_tmp) {
+ if ((e->connection.state == UA_CONNECTION_OPENING) &&
+ (now > (e->connection.openingDate + (NOHELLOTIMEOUT * UA_DATETIME_MSEC)))){
+ UA_LOG_INFO(layer->logger, UA_LOGCATEGORY_NETWORK,
+ "Connection %i | Closed by the server (no Hello Message)",
+ e->connection.sockfd);
+ LIST_REMOVE(e, pointers);
+ CLOSESOCKET(e->connection.sockfd);
+ UA_Server_removeConnection(server, &e->connection);
+ continue;
+ }
+
+ if(!UA_fd_isset(e->connection.sockfd, &errset) &&
+ !UA_fd_isset(e->connection.sockfd, &fdset))
+ continue;
+
+ UA_LOG_TRACE(layer->logger, UA_LOGCATEGORY_NETWORK,
+ "Connection %i | Activity on the socket",
+ e->connection.sockfd);
+
+ UA_ByteString buf = UA_BYTESTRING_NULL;
+ UA_StatusCode retval = connection_recv(&e->connection, &buf, 0);
+
+ if(retval == UA_STATUSCODE_GOOD) {
+ /* Process packets */
+ UA_Server_processBinaryMessage(server, &e->connection, &buf);
+ connection_releaserecvbuffer(&e->connection, &buf);
+ } else if(retval == UA_STATUSCODE_BADCONNECTIONCLOSED) {
+ /* The socket is shutdown but not closed */
+ UA_LOG_INFO(layer->logger, UA_LOGCATEGORY_NETWORK,
+ "Connection %i | Closed",
+ e->connection.sockfd);
+ LIST_REMOVE(e, pointers);
+ CLOSESOCKET(e->connection.sockfd);
+ UA_Server_removeConnection(server, &e->connection);
+ }
+ }
+ return UA_STATUSCODE_GOOD;
+}
+
+static void
+ServerNetworkLayerTCP_stop(UA_ServerNetworkLayer *nl, UA_Server *server) {
+ ServerNetworkLayerTCP *layer = (ServerNetworkLayerTCP *)nl->handle;
+ UA_LOG_INFO(layer->logger, UA_LOGCATEGORY_NETWORK,
+ "Shutting down the TCP network layer");
+
+ /* Close the server sockets */
+ for(UA_UInt16 i = 0; i < layer->serverSocketsSize; i++) {
+ shutdown((SOCKET)layer->serverSockets[i], 2);
+ CLOSESOCKET(layer->serverSockets[i]);
+ }
+ layer->serverSocketsSize = 0;
+
+ /* Close open connections */
+ ConnectionEntry *e;
+ LIST_FOREACH(e, &layer->connections, pointers)
+ ServerNetworkLayerTCP_close(&e->connection);
+
+ /* Run recv on client sockets. This picks up the closed sockets and frees
+ * the connection. */
+ ServerNetworkLayerTCP_listen(nl, server, 0);
+
+#ifdef _WIN32
+ WSACleanup();
+#endif
+}
+
+/* run only when the server is stopped */
+static void
+ServerNetworkLayerTCP_deleteMembers(UA_ServerNetworkLayer *nl) {
+ ServerNetworkLayerTCP *layer = (ServerNetworkLayerTCP *)nl->handle;
+ UA_String_deleteMembers(&nl->discoveryUrl);
+
+ /* Hard-close and remove remaining connections. The server is no longer
+ * running. So this is safe. */
+ ConnectionEntry *e, *e_tmp;
+ LIST_FOREACH_SAFE(e, &layer->connections, pointers, e_tmp) {
+ LIST_REMOVE(e, pointers);
+ CLOSESOCKET(e->connection.sockfd);
+ UA_free(e);
+ }
+
+ /* Free the layer */
+ UA_free(layer);
+}
+
+UA_ServerNetworkLayer
+UA_ServerNetworkLayerTCP(UA_ConnectionConfig conf, UA_UInt16 port, UA_Logger logger) {
+ UA_ServerNetworkLayer nl;
+ memset(&nl, 0, sizeof(UA_ServerNetworkLayer));
+ nl.start = ServerNetworkLayerTCP_start;
+ nl.listen = ServerNetworkLayerTCP_listen;
+ nl.stop = ServerNetworkLayerTCP_stop;
+ nl.deleteMembers = ServerNetworkLayerTCP_deleteMembers;
+
+ ServerNetworkLayerTCP *layer = (ServerNetworkLayerTCP*)
+ UA_calloc(1,sizeof(ServerNetworkLayerTCP));
+ if(!layer)
+ return nl;
+ nl.handle = layer;
+
+ layer->logger = (logger != NULL ? logger : UA_Log_Stdout);
+ layer->conf = conf;
+ layer->port = port;
+
+ return nl;
+}
+
+/***************************/
+/* Client NetworkLayer TCP */
+/***************************/
+
+static void
+ClientNetworkLayerTCP_close(UA_Connection *connection) {
+ if (connection->state == UA_CONNECTION_CLOSED)
+ return;
+ shutdown((SOCKET)connection->sockfd, 2);
+ CLOSESOCKET(connection->sockfd);
+ connection->state = UA_CONNECTION_CLOSED;
+}
+
+UA_Connection
+UA_ClientConnectionTCP(UA_ConnectionConfig conf,
+ const char *endpointUrl, const UA_UInt32 timeout,
+ UA_Logger logger) {
+#ifdef _WIN32
+ WORD wVersionRequested;
+ WSADATA wsaData;
+ wVersionRequested = MAKEWORD(2, 2);
+ WSAStartup(wVersionRequested, &wsaData);
+#endif
+
+ if(logger == NULL) {
+ logger = UA_Log_Stdout;
+ }
+
+ UA_Connection connection;
+ memset(&connection, 0, sizeof(UA_Connection));
+ connection.state = UA_CONNECTION_CLOSED;
+ connection.localConf = conf;
+ connection.remoteConf = conf;
+ connection.send = connection_write;
+ connection.recv = connection_recv;
+ connection.close = ClientNetworkLayerTCP_close;
+ connection.free = NULL;
+ connection.getSendBuffer = connection_getsendbuffer;
+ connection.releaseSendBuffer = connection_releasesendbuffer;
+ connection.releaseRecvBuffer = connection_releaserecvbuffer;
+
+ UA_String endpointUrlString = UA_STRING((char*)(uintptr_t)endpointUrl);
+ 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(&endpointUrlString, &hostnameString,
+ &port, &pathString);
+ if(parse_retval != UA_STATUSCODE_GOOD || hostnameString.length > 511) {
+ UA_LOG_WARNING(logger, UA_LOGCATEGORY_NETWORK,
+ "Server url is invalid: %s", endpointUrl);
+ 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 %d", port);
+ }
+
+ struct addrinfo hints, *server;
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_family = AF_UNSPEC;
+ hints.ai_socktype = SOCK_STREAM;
+#if defined(UA_FREERTOS)
+ hints.ai_protocol = IPPROTO_TCP;
+#endif
+ char portStr[6];
+#ifndef _MSC_VER
+ snprintf(portStr, 6, "%d", port);
+#else
+ _snprintf_s(portStr, 6, _TRUNCATE, "%d", port);
+#endif
+ int error = getaddrinfo(hostname, portStr, &hints, &server);
+ if(error != 0 || !server) {
+#if !defined(UA_FREERTOS)
+ UA_LOG_WARNING(logger, UA_LOGCATEGORY_NETWORK,
+
+ "DNS lookup of %s failed with error %s",
+ hostname, gai_strerror(error));
+#else
+ UA_LOG_WARNING(logger, UA_LOGCATEGORY_NETWORK,
+ "DNS lookup of %s failed with error",
+ hostname);
+#endif
+ return connection;
+ }
+
+ UA_Boolean connected = UA_FALSE;
+ UA_DateTime dtTimeout = timeout * UA_DATETIME_MSEC;
+ UA_DateTime connStart = UA_DateTime_nowMonotonic();
+ 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 = socket(server->ai_family,
+ server->ai_socktype,
+ server->ai_protocol);
+ #ifdef _WIN32
+ if(clientsockfd == INVALID_SOCKET) {
+ #else
+ if(clientsockfd < 0) {
+ #endif
+ UA_LOG_SOCKET_ERRNO_WRAP(UA_LOG_WARNING(logger, UA_LOGCATEGORY_NETWORK,
+ "Could not create client socket: %s", errno_str));
+ freeaddrinfo(server);
+ return connection;
+ }
+
+ connection.state = UA_CONNECTION_OPENING;
+
+ /* Connect to the server */
+ connection.sockfd = (UA_Int32) clientsockfd; /* cast for win32 */
+
+ /* Non blocking connect to be able to timeout */
+ if (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);
+ freeaddrinfo(server);
+ return connection;
+ }
+
+ /* Non blocking connect */
+ error = connect(clientsockfd, server->ai_addr, WIN32_INT server->ai_addrlen);
+
+ if ((error == -1) && (errno__ != 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",
+ endpointUrl, errno_str));
+ freeaddrinfo(server);
+ return connection;
+ }
+
+ /* Use select to wait and check if connected */
+ if (error == -1 && (errno__ == ERR_CONNECTION_PROGRESS)) {
+ /* connection in progress. Wait until connected using select */
+ UA_DateTime timeSinceStart = UA_DateTime_nowMonotonic() - connStart;
+ if(timeSinceStart > dtTimeout)
+ break;
+
+ 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),
+ (long int) (timeout_usec % 1000000)};
+
+ int resultsize = select((UA_Int32)(clientsockfd + 1), NULL, &fdset, NULL, &tmptv);
+
+ 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 = 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",
+ endpointUrl, strerror(ret == 0 ? so_error : errno__));
+ 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);
+
+ freeaddrinfo(server);
+
+ if(!connected) {
+ /* connection timeout */
+ if (connection.state != UA_CONNECTION_CLOSED)
+ ClientNetworkLayerTCP_close(&connection);
+ UA_LOG_WARNING(logger, UA_LOGCATEGORY_NETWORK,
+ "Trying to connect to %s timed out",
+ endpointUrl);
+ return connection;
+ }
+
+
+ /* We are connected. Reset socket to blocking */
+ if(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 = 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;
+}
+
+/*********************************** amalgamated original file "/home/jvoe/open62541/plugins/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.
+ *
+ * Copyright 2016-2017 (c) Julius Pfrommer, Fraunhofer IOSB
+ * Copyright 2017 (c) Stefan Profanter, fortiss GmbH
+ * Copyright 2017 (c) Thomas Stalder, Blue Time Concept SA
+ */
+
+/* Enable POSIX features */
+#if !defined(_XOPEN_SOURCE) && !defined(_WRS_KERNEL)
+# define _XOPEN_SOURCE 600
+#endif
+#ifndef _DEFAULT_SOURCE
+# define _DEFAULT_SOURCE
+#endif
+/* On older systems we need to define _BSD_SOURCE.
+ * _DEFAULT_SOURCE is an alias for that. */
+#ifndef _BSD_SOURCE
+# define _BSD_SOURCE
+#endif
+
+#include <time.h>
+#ifdef _WIN32
+/* Backup definition of SLIST_ENTRY on mingw winnt.h */
+# ifdef SLIST_ENTRY
+# pragma push_macro("SLIST_ENTRY")
+# undef SLIST_ENTRY
+# define POP_SLIST_ENTRY
+# endif
+# include <windows.h>
+/* restore definition */
+# ifdef POP_SLIST_ENTRY
+# undef SLIST_ENTRY
+# undef POP_SLIST_ENTRY
+# pragma pop_macro("SLIST_ENTRY")
+# endif
+#else
+# include <sys/time.h>
+#endif
+
+#if defined(__APPLE__) || defined(__MACH__)
+# include <mach/clock.h>
+# include <mach/mach.h>
+#endif
+
+
+#if defined(UA_FREERTOS)
+#include <task.h>
+#endif
+
+UA_DateTime UA_DateTime_now(void) {
+#if defined(_WIN32)
+ /* Windows filetime has the same definition as UA_DateTime */
+ FILETIME ft;
+ SYSTEMTIME st;
+ GetSystemTime(&st);
+ SystemTimeToFileTime(&st, &ft);
+ ULARGE_INTEGER ul;
+ ul.LowPart = ft.dwLowDateTime;
+ ul.HighPart = ft.dwHighDateTime;
+ return (UA_DateTime)ul.QuadPart;
+#else
+ struct timeval tv;
+ gettimeofday(&tv, NULL);
+ return (tv.tv_sec * UA_DATETIME_SEC) + (tv.tv_usec * UA_DATETIME_USEC) + UA_DATETIME_UNIX_EPOCH;
+#endif
+}
+
+/* Credit to https://stackoverflow.com/questions/13804095/get-the-time-zone-gmt-offset-in-c */
+UA_Int64 UA_DateTime_localTimeUtcOffset(void) {
+ time_t gmt, rawtime = time(NULL);
+
+#ifdef _WIN32
+ struct tm ptm;
+ gmtime_s(&ptm, &rawtime);
+ // Request that mktime() looksup dst in timezone database
+ ptm.tm_isdst = -1;
+ gmt = mktime(&ptm);
+#else
+ struct tm *ptm;
+ struct tm gbuf;
+ ptm = gmtime_r(&rawtime, &gbuf);
+ // Request that mktime() looksup dst in timezone database
+ ptm->tm_isdst = -1;
+ gmt = mktime(ptm);
+#endif
+
+ return (UA_Int64) (difftime(rawtime, gmt) * UA_DATETIME_SEC);
+}
+
+UA_DateTime UA_DateTime_nowMonotonic(void) {
+#if defined(_WIN32)
+ LARGE_INTEGER freq, ticks;
+ QueryPerformanceFrequency(&freq);
+ QueryPerformanceCounter(&ticks);
+ UA_Double ticks2dt = UA_DATETIME_SEC / (UA_Double)freq.QuadPart;
+ return (UA_DateTime)(ticks.QuadPart * ticks2dt);
+#elif defined(__APPLE__) || defined(__MACH__)
+ /* OS X does not have clock_gettime, use clock_get_time */
+ clock_serv_t cclock;
+ mach_timespec_t mts;
+ host_get_clock_service(mach_host_self(), SYSTEM_CLOCK, &cclock);
+ clock_get_time(cclock, &mts);
+ mach_port_deallocate(mach_task_self(), cclock);
+ return (mts.tv_sec * UA_DATETIME_SEC) + (mts.tv_nsec / 100);
+#elif !defined(CLOCK_MONOTONIC_RAW)
+# if defined(UA_FREERTOS)
+ portTickType TaskTime = xTaskGetTickCount();
+ UA_DateTimeStruct UATime;
+ UATime.milliSec = (UA_UInt16) TaskTime;
+ struct timespec ts;
+ ts.tv_sec = UATime.milliSec/1000;
+ ts.tv_nsec = (UATime.milliSec % 1000)* 1000000;
+ return (ts.tv_sec * UA_DATETIME_SEC) + (ts.tv_nsec / 100);
+# else
+ struct timespec ts;
+ clock_gettime(CLOCK_MONOTONIC, &ts);
+ return (ts.tv_sec * UA_DATETIME_SEC) + (ts.tv_nsec / 100);
+# endif
+#else
+ struct timespec ts;
+ clock_gettime(CLOCK_MONOTONIC_RAW, &ts);
+ return (ts.tv_sec * UA_DATETIME_SEC) + (ts.tv_nsec / 100);
+#endif
+}
+
+/*********************************** amalgamated original file "/home/jvoe/open62541/plugins/ua_log_stdout.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) Julius Pfrommer, Fraunhofer IOSB
+ * Copyright 2017 (c) Thomas Stalder, Blue Time Concept SA
+ */
+
+#include <stdio.h>
+
+/* ANSI escape sequences for color output taken from here:
+ * https://stackoverflow.com/questions/3219393/stdlib-and-colored-output-in-c*/
+
+#ifdef _WIN32
+# 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 ""
+#else
+# 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"
+#endif
+
+#ifdef UA_ENABLE_MULTITHREADING
+#include <pthread.h>
+static pthread_mutex_t printf_mutex = PTHREAD_MUTEX_INITIALIZER;
+#endif
+
+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"};
+
+#ifdef __clang__
+__attribute__((__format__(__printf__, 3 , 0)))
+#endif
+void
+UA_Log_Stdout(UA_LogLevel level, UA_LogCategory category,
+ const char *msg, va_list args) {
+ UA_Int64 tOffset = UA_DateTime_localTimeUtcOffset();
+ UA_DateTimeStruct dts = UA_DateTime_toStruct(UA_DateTime_now() + tOffset);
+
+#ifdef UA_ENABLE_MULTITHREADING
+ pthread_mutex_lock(&printf_mutex);
+#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);
+
+#ifdef UA_ENABLE_MULTITHREADING
+ pthread_mutex_unlock(&printf_mutex);
+#endif
+}
+
+/*********************************** amalgamated original file "/home/jvoe/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) Julius Pfrommer, Fraunhofer IOSB
+ * Copyright 2017 (c) Stefan Profanter, fortiss GmbH
+ */
+
+
+/* Example access control management. Anonymous and username / password login.
+ * The access rights are maximally permissive. */
+
+typedef struct {
+ UA_Boolean allowAnonymous;
+ size_t usernamePasswordLoginSize;
+ UA_UsernamePasswordLogin *usernamePasswordLogin;
+} AccessControlContext;
+
+#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);
+
+/************************/
+/* Access Control Logic */
+/************************/
+
+static UA_StatusCode
+activateSession_default(UA_Server *server, UA_AccessControl *ac,
+ const UA_NodeId *sessionId,
+ const UA_ExtensionObject *userIdentityToken,
+ void **sessionContext) {
+ AccessControlContext *context = (AccessControlContext*)ac->context;
+
+ /* The empty token is interpreted as anonymous */
+ if(userIdentityToken->encoding == UA_EXTENSIONOBJECT_ENCODED_NOBODY) {
+ if(!context->allowAnonymous)
+ return UA_STATUSCODE_BADIDENTITYTOKENINVALID;
+
+ /* No userdata atm */
+ *sessionContext = NULL;
+ return UA_STATUSCODE_GOOD;
+ }
+
+ /* Could the token be decoded? */
+ if(userIdentityToken->encoding < UA_EXTENSIONOBJECT_DECODED)
+ return UA_STATUSCODE_BADIDENTITYTOKENINVALID;
+
+ /* Anonymous login */
+ if(userIdentityToken->content.decoded.type == &UA_TYPES[UA_TYPES_ANONYMOUSIDENTITYTOKEN]) {
+ if(!context->allowAnonymous)
+ return UA_STATUSCODE_BADIDENTITYTOKENINVALID;
+
+ const UA_AnonymousIdentityToken *token = (UA_AnonymousIdentityToken*)
+ userIdentityToken->content.decoded.data;
+
+ /* 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;
+
+ /* No userdata atm */
+ *sessionContext = NULL;
+ return UA_STATUSCODE_GOOD;
+ }
+
+ /* 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;
+
+ /* TODO: Support encrypted username/password over unencrypted SecureChannels */
+ if(userToken->encryptionAlgorithm.length > 0)
+ return UA_STATUSCODE_BADIDENTITYTOKENINVALID;
+
+ /* Empty username and password */
+ if(userToken->userName.length == 0 && userToken->password.length == 0)
+ return UA_STATUSCODE_BADIDENTITYTOKENINVALID;
+
+ /* 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;
+
+ /* No userdata atm */
+ *sessionContext = NULL;
+ return UA_STATUSCODE_GOOD;
+ }
+
+ /* Unsupported token type */
+ return UA_STATUSCODE_BADIDENTITYTOKENINVALID;
+}
+
+static void
+closeSession_default(UA_Server *server, UA_AccessControl *ac,
+ const UA_NodeId *sessionId, void *sessionContext) {
+ /* no context to clean up */
+}
+
+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_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_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_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_Boolean
+allowAddNode_default(UA_Server *server, UA_AccessControl *ac,
+ const UA_NodeId *sessionId, void *sessionContext,
+ const UA_AddNodesItem *item) {
+ return true;
+}
+
+static UA_Boolean
+allowAddReference_default(UA_Server *server, UA_AccessControl *ac,
+ const UA_NodeId *sessionId, void *sessionContext,
+ const UA_AddReferencesItem *item) {
+ return true;
+}
+
+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_Boolean
+allowDeleteReference_default(UA_Server *server, UA_AccessControl *ac,
+ const UA_NodeId *sessionId, void *sessionContext,
+ const UA_DeleteReferencesItem *item) {
+ return true;
+}
+
+/***************************************/
+/* Create Delete Access Control Plugin */
+/***************************************/
+
+static void deleteMembers_default(UA_AccessControl *ac) {
+ UA_Array_delete((void*)(uintptr_t)ac->userTokenPolicies,
+ ac->userTokenPoliciesSize,
+ &UA_TYPES[UA_TYPES_USERTOKENPOLICY]);
+
+ AccessControlContext *context = (AccessControlContext*)ac->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);
+}
+
+UA_AccessControl
+UA_AccessControl_default(UA_Boolean allowAnonymous, size_t usernamePasswordLoginSize,
+ const UA_UsernamePasswordLogin *usernamePasswordLogin) {
+ AccessControlContext *context = (AccessControlContext*)
+ UA_malloc(sizeof(AccessControlContext));
+
+ UA_AccessControl ac;
+ memset(&ac, 0, sizeof(ac));
+ ac.context = context;
+ ac.deleteMembers = deleteMembers_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.allowDeleteNode = allowDeleteNode_default;
+ ac.allowDeleteReference = allowDeleteReference_default;
+
+ /* 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)
+ return ac;
+ 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 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 ac;
+ ac.userTokenPoliciesSize = policies;
+
+ policies = 0;
+ if(allowAnonymous) {
+ ac.userTokenPolicies[policies].tokenType = UA_USERTOKENTYPE_ANONYMOUS;
+ ac.userTokenPolicies[policies].policyId = UA_STRING_ALLOC(ANONYMOUS_POLICY);
+ policies++;
+ }
+
+ if(usernamePasswordLoginSize > 0) {
+ ac.userTokenPolicies[policies].tokenType = UA_USERTOKENTYPE_USERNAME;
+ ac.userTokenPolicies[policies].policyId = UA_STRING_ALLOC(USERNAME_POLICY);
+ /* No encryption of username/password supported at the moment */
+ ac.userTokenPolicies[policies].securityPolicyUri =
+ UA_STRING_ALLOC("http://opcfoundation.org/UA/SecurityPolicy#None");
+ }
+ return ac;
+}
+
+/*********************************** amalgamated original file "/home/jvoe/open62541/plugins/ua_pki_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.
+ *
+ * Copyright 2018 (c) Mark Giraud, Fraunhofer IOSB
+ */
+
+
+#ifdef UA_ENABLE_ENCRYPTION
+#include <mbedtls/x509.h>
+#include <mbedtls/x509_crt.h>
+#endif
+
+/************/
+/* AllowAll */
+/************/
+
+static UA_StatusCode
+verifyCertificateAllowAll(void *verificationContext,
+ const UA_ByteString *certificate) {
+ return UA_STATUSCODE_GOOD;
+}
+
+static UA_StatusCode
+verifyApplicationURIAllowAll(void *verificationContext,
+ const UA_ByteString *certificate,
+ const UA_String *applicationURI) {
+ return UA_STATUSCODE_GOOD;
+}
+
+static void
+deleteVerifyAllowAll(UA_CertificateVerification *cv) {
+
+}
+
+void UA_CertificateVerification_AcceptAll(UA_CertificateVerification *cv) {
+ cv->verifyCertificate = verifyCertificateAllowAll;
+ cv->verifyApplicationURI = verifyApplicationURIAllowAll;
+ cv->deleteMembers = deleteVerifyAllowAll;
+}
+
+#ifdef UA_ENABLE_ENCRYPTION
+
+typedef struct {
+ mbedtls_x509_crt certificateTrustList;
+ mbedtls_x509_crl certificateRevocationList;
+} CertInfo;
+
+static UA_StatusCode
+certificateVerification_verify(void *verificationContext,
+ const UA_ByteString *certificate) {
+ CertInfo *ci = (CertInfo*)verificationContext;
+ if(!ci)
+ 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) {
+ /* 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;
+ }
+
+ /* 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
+
+ uint32_t flags = 0;
+ mbedErr = mbedtls_x509_crt_verify_with_profile(&remoteCertificate,
+ &ci->certificateTrustList,
+ &ci->certificateRevocationList,
+ &crtProfile, NULL, &flags, NULL, NULL);
+
+ // TODO: Extend verification
+ UA_StatusCode retval = UA_STATUSCODE_GOOD;
+ if(mbedErr) {
+ /* char buff[100]; */
+ /* mbedtls_x509_crt_verify_info(buff, 100, "", flags); */
+ /* UA_LOG_ERROR(channelContextData->policyContext->securityPolicy->logger, */
+ /* UA_LOGCATEGORY_SECURITYPOLICY, */
+ /* "Verifying the certificate failed with error: %s", buff); */
+
+ if(flags & MBEDTLS_X509_BADCERT_NOT_TRUSTED) {
+ retval = UA_STATUSCODE_BADCERTIFICATEUNTRUSTED;
+ } else if (flags & MBEDTLS_X509_BADCERT_FUTURE ||
+ flags & MBEDTLS_X509_BADCERT_EXPIRED) {
+ retval = UA_STATUSCODE_BADCERTIFICATETIMEINVALID;
+ } else if(flags & MBEDTLS_X509_BADCERT_REVOKED ||
+ flags & MBEDTLS_X509_BADCRL_EXPIRED) {
+ retval = UA_STATUSCODE_BADCERTIFICATEREVOKED;
+ } else {
+ retval = UA_STATUSCODE_BADSECURITYCHECKSFAILED;
+ }
+ }
+
+ mbedtls_x509_crt_free(&remoteCertificate);
+ return retval;
+}
+
+/* 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*/
+ /* handle special case */
+ if(l == 0)
+ return (NULL);
+
+ for(; *s != ch; ++s, --l)
+ if(l == 0)
+ return (NULL);
+ return s;
+}
+
+static const unsigned char *
+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;
+}
+
+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;
+
+ /* 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;
+
+ /* 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(bstrstr(remoteCertificate.v3_ext.p, remoteCertificate.v3_ext.len,
+ applicationURI->data, applicationURI->length) == NULL)
+ retval = UA_STATUSCODE_BADCERTIFICATEURIINVALID;
+
+ mbedtls_x509_crt_free(&remoteCertificate);
+ return retval;
+}
+
+static void
+certificateVerification_deleteMembers(UA_CertificateVerification *cv) {
+ CertInfo *ci = (CertInfo*)cv->context;
+ if(!ci)
+ return;
+ mbedtls_x509_crt_free(&ci->certificateTrustList);
+ mbedtls_x509_crl_free(&ci->certificateRevocationList);
+ UA_free(ci);
+ cv->context = NULL;
+}
+
+UA_StatusCode
+UA_CertificateVerification_Trustlist(UA_CertificateVerification *cv,
+ const UA_ByteString *certificateTrustList,
+ size_t certificateTrustListSize,
+ const UA_ByteString *certificateRevocationList,
+ size_t certificateRevocationListSize) {
+ CertInfo *ci = (CertInfo*)malloc(sizeof(CertInfo));
+ if(!ci)
+ return UA_STATUSCODE_BADOUTOFMEMORY;
+ mbedtls_x509_crt_init(&ci->certificateTrustList);
+ mbedtls_x509_crl_init(&ci->certificateRevocationList);
+
+ cv->context = (void*)ci;
+ if(certificateTrustListSize > 0)
+ cv->verifyCertificate = certificateVerification_verify;
+ else
+ cv->verifyCertificate = verifyCertificateAllowAll;
+ cv->deleteMembers = certificateVerification_deleteMembers;
+ cv->verifyApplicationURI = certificateVerification_verifyApplicationURI;
+
+ int err = 0;
+ for(size_t i = 0; i < certificateTrustListSize; i++) {
+ err |= mbedtls_x509_crt_parse(&ci->certificateTrustList,
+ certificateTrustList[i].data,
+ certificateTrustList[i].length);
+ }
+ for(size_t i = 0; i < certificateRevocationListSize; i++) {
+ err |= mbedtls_x509_crl_parse(&ci->certificateRevocationList,
+ certificateRevocationList[i].data,
+ certificateRevocationList[i].length);
+ }
+
+ if(err) {
+ certificateVerification_deleteMembers(cv);
+ return UA_STATUSCODE_BADINTERNALERROR;
+ }
+ return UA_STATUSCODE_GOOD;
+}
+
+#endif
+
+/*********************************** amalgamated original file "/home/jvoe/open62541/plugins/ua_nodestore_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) Julian Grothoff
+ * Copyright 2017 (c) Stefan Profanter, fortiss GmbH
+ */
+
+
+/* container_of */
+#define container_of(ptr, type, member) \
+ (type *)((uintptr_t)ptr - offsetof(type,member))
+
+#ifdef UA_ENABLE_MULTITHREADING
+#include <pthread.h>
+#define BEGIN_CRITSECT(NODEMAP) pthread_mutex_lock(&(NODEMAP)->mutex)
+#define END_CRITSECT(NODEMAP) pthread_mutex_unlock(&(NODEMAP)->mutex)
+#else
+#define BEGIN_CRITSECT(NODEMAP)
+#define END_CRITSECT(NODEMAP)
+#endif
+
+/* 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 **entries;
+ UA_UInt32 size;
+ UA_UInt32 count;
+ UA_UInt32 sizePrimeIndex;
+#ifdef UA_ENABLE_MULTITHREADING
+ pthread_mutex_t mutex; /* Protect access */
+#endif
+} 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 low;
+}
+
+/* returns an empty slot or null if the nodeid exists or if no empty slot is found. */
+static UA_NodeMapEntry **
+findFreeSlot(const UA_NodeMap *ns, const UA_NodeId *nodeid) {
+ UA_NodeMapEntry **retval = NULL;
+ UA_UInt32 h = UA_NodeId_hash(nodeid);
+ UA_UInt32 size = ns->size;
+ UA_UInt64 idx = mod(h, size); // use 64 bit container to avoid overflow
+ UA_UInt32 startIdx = (UA_UInt32)idx;
+ UA_UInt32 hash2 = mod2(h, size);
+ UA_NodeMapEntry *entry = NULL;
+
+ do {
+ entry = ns->entries[(UA_UInt32)idx];
+ if(entry > UA_NODEMAP_TOMBSTONE &&
+ UA_NodeId_equal(&entry->node.nodeId, nodeid))
+ return NULL;
+ if(!retval && entry <= UA_NODEMAP_TOMBSTONE)
+ retval = &ns->entries[(UA_UInt32)idx];
+ idx += hash2;
+ if(idx >= size)
+ idx -= size;
+ } while((UA_UInt32)idx != startIdx && entry);
+
+ /* NULL is returned if there is no free slot (idx == startIdx).
+ * Otherwise the first free slot is returned after we are sure,
+ * that the node id cannot be found in the used hashmap (!entry). */
+ return retval;
+}
+
+/* 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;
+
+ UA_NodeMapEntry **oentries = ns->entries;
+ UA_UInt32 nindex = higher_prime_index(count * 2);
+ UA_UInt32 nsize = primes[nindex];
+ UA_NodeMapEntry **nentries = (UA_NodeMapEntry **)UA_calloc(nsize, sizeof(UA_NodeMapEntry*));
+ if(!nentries)
+ return UA_STATUSCODE_BADOUTOFMEMORY;
+
+ ns->entries = nentries;
+ 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(oentries[i] <= UA_NODEMAP_TOMBSTONE)
+ continue;
+ UA_NodeMapEntry **e = findFreeSlot(ns, &oentries[i]->node.nodeId);
+ UA_assert(e);
+ *e = oentries[i];
+ ++j;
+ }
+
+ UA_free(oentries);
+ return UA_STATUSCODE_GOOD;
+}
+
+static UA_NodeMapEntry *
+newEntry(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.nodeClass = nodeClass;
+ return entry;
+}
+
+static void
+deleteEntry(UA_NodeMapEntry *entry) {
+ UA_Node_deleteMembers(&entry->node);
+ UA_free(entry);
+}
+
+static void
+cleanupEntry(UA_NodeMapEntry *entry) {
+ if(entry->deleted && entry->refCount == 0)
+ deleteEntry(entry);
+}
+
+static UA_StatusCode
+clearSlot(UA_NodeMap *ns, UA_NodeMapEntry **slot) {
+ (*slot)->deleted = true;
+ cleanupEntry(*slot);
+ *slot = UA_NODEMAP_TOMBSTONE;
+ --ns->count;
+ /* Downsize the hashmap if it is very empty */
+ if(ns->count * 8 < ns->size && ns->size > 32)
+ expand(ns); /* Can fail. Just continue with the bigger hashmap. */
+ return UA_STATUSCODE_GOOD;
+}
+
+static UA_NodeMapEntry **
+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 64 bit container to avoid overflow
+ UA_UInt32 hash2 = mod2(h, size);
+ UA_UInt32 startIdx = (UA_UInt32)idx;
+ UA_NodeMapEntry *entry = NULL;
+
+ do {
+ entry = ns->entries[(UA_UInt32)idx];
+ if(entry > UA_NODEMAP_TOMBSTONE &&
+ UA_NodeId_equal(&entry->node.nodeId, nodeid))
+ return &ns->entries[(UA_UInt32)idx];
+ idx += hash2;
+ if(idx >= size)
+ idx -= size;
+ } while((UA_UInt32)idx != startIdx && entry);
+
+ /* NULL is returned if there is no free slot (idx == startIdx)
+ * and the node id is not found or if the end of the used slots (!entry)
+ * is reached. */
+ return NULL;
+}
+
+/***********************/
+/* Interface functions */
+/***********************/
+
+static UA_Node *
+UA_NodeMap_newNode(void *context, UA_NodeClass nodeClass) {
+ UA_NodeMapEntry *entry = newEntry(nodeClass);
+ if(!entry)
+ return NULL;
+ return &entry->node;
+}
+
+static void
+UA_NodeMap_deleteNode(void *context, UA_Node *node) {
+#ifdef UA_ENABLE_MULTITHREADING
+ UA_NodeMap *ns = (UA_NodeMap*)context;
+#endif
+ BEGIN_CRITSECT(ns);
+ UA_NodeMapEntry *entry = container_of(node, UA_NodeMapEntry, node);
+ UA_assert(&entry->node == node);
+ deleteEntry(entry);
+ END_CRITSECT(ns);
+}
+
+static const UA_Node *
+UA_NodeMap_getNode(void *context, const UA_NodeId *nodeid) {
+ UA_NodeMap *ns = (UA_NodeMap*)context;
+ BEGIN_CRITSECT(ns);
+ UA_NodeMapEntry **entry = findOccupiedSlot(ns, nodeid);
+ if(!entry) {
+ END_CRITSECT(ns);
+ return NULL;
+ }
+ ++(*entry)->refCount;
+ END_CRITSECT(ns);
+ return (const UA_Node*)&(*entry)->node;
+}
+
+static void
+UA_NodeMap_releaseNode(void *context, const UA_Node *node) {
+ if (!node)
+ return;
+#ifdef UA_ENABLE_MULTITHREADING
+ UA_NodeMap *ns = (UA_NodeMap*)context;
+#endif
+ BEGIN_CRITSECT(ns);
+ UA_NodeMapEntry *entry = container_of(node, UA_NodeMapEntry, node);
+ UA_assert(&entry->node == node);
+ UA_assert(entry->refCount > 0);
+ --entry->refCount;
+ cleanupEntry(entry);
+ END_CRITSECT(ns);
+}
+
+static UA_StatusCode
+UA_NodeMap_getNodeCopy(void *context, const UA_NodeId *nodeid,
+ UA_Node **outNode) {
+ UA_NodeMap *ns = (UA_NodeMap*)context;
+ BEGIN_CRITSECT(ns);
+ UA_NodeMapEntry **slot = findOccupiedSlot(ns, nodeid);
+ if(!slot) {
+ END_CRITSECT(ns);
+ return UA_STATUSCODE_BADNODEIDUNKNOWN;
+ }
+ UA_NodeMapEntry *entry = *slot;
+ UA_NodeMapEntry *newItem = newEntry(entry->node.nodeClass);
+ if(!newItem) {
+ END_CRITSECT(ns);
+ 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 {
+ deleteEntry(newItem);
+ }
+ END_CRITSECT(ns);
+ return retval;
+}
+
+static UA_StatusCode
+UA_NodeMap_removeNode(void *context, const UA_NodeId *nodeid) {
+ UA_NodeMap *ns = (UA_NodeMap*)context;
+ BEGIN_CRITSECT(ns);
+ UA_NodeMapEntry **slot = findOccupiedSlot(ns, nodeid);
+ UA_StatusCode retval = UA_STATUSCODE_GOOD;
+ if(slot)
+ retval = clearSlot(ns, slot);
+ else
+ retval = UA_STATUSCODE_BADNODEIDUNKNOWN;
+ END_CRITSECT(ns);
+ return retval;
+}
+
+static UA_StatusCode
+UA_NodeMap_insertNode(void *context, UA_Node *node,
+ UA_NodeId *addedNodeId) {
+ UA_NodeMap *ns = (UA_NodeMap*)context;
+ BEGIN_CRITSECT(ns);
+ if(ns->size * 3 <= ns->count * 4) {
+ if(expand(ns) != UA_STATUSCODE_GOOD) {
+ END_CRITSECT(ns);
+ return UA_STATUSCODE_BADINTERNALERROR;
+ }
+ }
+
+ UA_NodeMapEntry **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, size); // start value, use 64 bit container 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
+
+ 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);
+
+ if (!slot) {
+ END_CRITSECT(ns);
+ return UA_STATUSCODE_BADOUTOFMEMORY;
+ }
+ } else {
+ slot = findFreeSlot(ns, &node->nodeId);
+ if(!slot) {
+ deleteEntry(container_of(node, UA_NodeMapEntry, node));
+ END_CRITSECT(ns);
+ return UA_STATUSCODE_BADNODEIDEXISTS;
+ }
+ }
+
+ *slot = container_of(node, UA_NodeMapEntry, node);
+ ++ns->count;
+ UA_assert(&(*slot)->node == node);
+
+ UA_StatusCode retval = UA_STATUSCODE_GOOD;
+ if(addedNodeId) {
+ retval = UA_NodeId_copy(&node->nodeId, addedNodeId);
+ if(retval != UA_STATUSCODE_GOOD)
+ clearSlot(ns, slot);
+ }
+
+ END_CRITSECT(ns);
+ return retval;
+}
+
+static UA_StatusCode
+UA_NodeMap_replaceNode(void *context, UA_Node *node) {
+ UA_NodeMap *ns = (UA_NodeMap*)context;
+ BEGIN_CRITSECT(ns);
+ UA_NodeMapEntry **slot = findOccupiedSlot(ns, &node->nodeId);
+ if(!slot) {
+ END_CRITSECT(ns);
+ return UA_STATUSCODE_BADNODEIDUNKNOWN;
+ }
+ UA_NodeMapEntry *newEntryContainer = container_of(node, UA_NodeMapEntry, node);
+ if(*slot != newEntryContainer->orig) {
+ /* The node was updated since the copy was made */
+ deleteEntry(newEntryContainer);
+ END_CRITSECT(ns);
+ return UA_STATUSCODE_BADINTERNALERROR;
+ }
+ (*slot)->deleted = true;
+ cleanupEntry(*slot);
+ *slot = newEntryContainer;
+ END_CRITSECT(ns);
+ return UA_STATUSCODE_GOOD;
+}
+
+static void
+UA_NodeMap_iterate(void *context, void *visitorContext,
+ UA_NodestoreVisitor visitor) {
+ UA_NodeMap *ns = (UA_NodeMap*)context;
+ BEGIN_CRITSECT(ns);
+ for(UA_UInt32 i = 0; i < ns->size; ++i) {
+ if(ns->entries[i] > UA_NODEMAP_TOMBSTONE) {
+ END_CRITSECT(ns);
+ UA_NodeMapEntry *entry = ns->entries[i];
+ entry->refCount++;
+ visitor(visitorContext, &entry->node);
+ entry->refCount--;
+ cleanupEntry(entry);
+ BEGIN_CRITSECT(ns);
+ }
+ }
+ END_CRITSECT(ns);
+}
+
+static void
+UA_NodeMap_delete(void *context) {
+ UA_NodeMap *ns = (UA_NodeMap*)context;
+#ifdef UA_ENABLE_MULTITHREADING
+ pthread_mutex_destroy(&ns->mutex);
+#endif
+ UA_UInt32 size = ns->size;
+ UA_NodeMapEntry **entries = ns->entries;
+ for(UA_UInt32 i = 0; i < size; ++i) {
+ if(entries[i] > UA_NODEMAP_TOMBSTONE) {
+ /* On debugging builds, check that all nodes were release */
+ UA_assert(entries[i]->refCount == 0);
+ /* Delete the node */
+ deleteEntry(entries[i]);
+ }
+ }
+ UA_free(ns->entries);
+ UA_free(ns);
+}
+
+UA_StatusCode
+UA_Nodestore_default_new(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->entries = (UA_NodeMapEntry**)
+ UA_calloc(nodemap->size, sizeof(UA_NodeMapEntry*));
+ if(!nodemap->entries) {
+ UA_free(nodemap);
+ return UA_STATUSCODE_BADOUTOFMEMORY;
+ }
+#ifdef UA_ENABLE_MULTITHREADING
+ pthread_mutex_init(&nodemap->mutex, NULL);
+#endif
+
+ /* Populate the nodestore */
+ ns->context = nodemap;
+ ns->deleteNodestore = UA_NodeMap_delete;
+ ns->inPlaceEditAllowed = true;
+ 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;
+}
+
+/*********************************** amalgamated original file "/home/jvoe/open62541/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) Julius Pfrommer, Fraunhofer IOSB
+ * 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
+ */
+
+
+#ifdef UA_ENABLE_ENCRYPTION
+#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 UA_INLINE UA_DurationRange
+UA_DURATIONRANGE(UA_Duration min, UA_Duration max) {
+ UA_DurationRange range = {min, max};
+ return range;
+}
+
+/*******************************/
+/* Default Connection Settings */
+/*******************************/
+
+const UA_ConnectionConfig UA_ConnectionConfig_default = {
+ 0, /* .protocolVersion */
+ 65535, /* .sendBufferSize, 64k per chunk */
+ 65535, /* .recvBufferSize, 64k per chunk */
+ 0, /* .maxMessageSize, 0 -> unlimited */
+ 0 /* .maxChunkCount, 0 -> unlimited */
+};
+
+/***************************/
+/* Default Server Settings */
+/***************************/
+
+#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 STRINGIFY(arg) #arg
+#define VERSION(MAJOR, MINOR, PATCH, LABEL) \
+ STRINGIFY(MAJOR) "." STRINGIFY(MINOR) "." STRINGIFY(PATCH) LABEL
+
+static UA_StatusCode
+createSecurityPolicyNoneEndpoint(UA_ServerConfig *conf, UA_Endpoint *endpoint,
+ const UA_ByteString localCertificate) {
+ UA_EndpointDescription_init(&endpoint->endpointDescription);
+
+ UA_SecurityPolicy_None(&endpoint->securityPolicy, NULL, localCertificate, conf->logger);
+ endpoint->endpointDescription.securityMode = UA_MESSAGESECURITYMODE_NONE;
+ endpoint->endpointDescription.securityPolicyUri =
+ UA_STRING_ALLOC("http://opcfoundation.org/UA/SecurityPolicy#None");
+ endpoint->endpointDescription.transportProfileUri =
+ UA_STRING_ALLOC("http://opcfoundation.org/UA-Profile/Transport/uatcp-uasc-uabinary");
+
+ /* Enable all login mechanisms from the access control plugin */
+ UA_StatusCode retval = UA_Array_copy(conf->accessControl.userTokenPolicies,
+ conf->accessControl.userTokenPoliciesSize,
+ (void **)&endpoint->endpointDescription.userIdentityTokens,
+ &UA_TYPES[UA_TYPES_USERTOKENPOLICY]);
+ if(retval != UA_STATUSCODE_GOOD)
+ return retval;
+ endpoint->endpointDescription.userIdentityTokensSize =
+ conf->accessControl.userTokenPoliciesSize;
+
+ UA_String_copy(&localCertificate, &endpoint->endpointDescription.serverCertificate);
+ UA_ApplicationDescription_copy(&conf->applicationDescription,
+ &endpoint->endpointDescription.server);
+
+ return UA_STATUSCODE_GOOD;
+}
+
+void
+UA_ServerConfig_set_customHostname(UA_ServerConfig *config, const UA_String customHostname) {
+ if(!config)
+ return;
+ UA_String_deleteMembers(&config->customHostname);
+ UA_String_copy(&customHostname, &config->customHostname);
+}
+
+#ifdef UA_ENABLE_ENCRYPTION
+
+static UA_StatusCode
+createSecurityPolicyBasic128Rsa15Endpoint(UA_ServerConfig *const conf,
+ UA_Endpoint *endpoint,
+ UA_MessageSecurityMode securityMode,
+ const UA_ByteString localCertificate,
+ const UA_ByteString localPrivateKey) {
+ UA_EndpointDescription_init(&endpoint->endpointDescription);
+
+ UA_StatusCode retval =
+ UA_SecurityPolicy_Basic128Rsa15(&endpoint->securityPolicy, &conf->certificateVerification,
+ localCertificate, localPrivateKey, conf->logger);
+ if(retval != UA_STATUSCODE_GOOD) {
+ endpoint->securityPolicy.deleteMembers(&endpoint->securityPolicy);
+ return retval;
+ }
+
+ endpoint->endpointDescription.securityMode = securityMode;
+ endpoint->endpointDescription.securityPolicyUri =
+ UA_STRING_ALLOC("http://opcfoundation.org/UA/SecurityPolicy#Basic128Rsa15");
+ endpoint->endpointDescription.transportProfileUri =
+ UA_STRING_ALLOC("http://opcfoundation.org/UA-Profile/Transport/uatcp-uasc-uabinary");
+
+ /* Enable all login mechanisms from the access control plugin */
+ retval = UA_Array_copy(conf->accessControl.userTokenPolicies,
+ conf->accessControl.userTokenPoliciesSize,
+ (void **)&endpoint->endpointDescription.userIdentityTokens,
+ &UA_TYPES[UA_TYPES_USERTOKENPOLICY]);
+ if(retval != UA_STATUSCODE_GOOD)
+ return retval;
+ endpoint->endpointDescription.userIdentityTokensSize =
+ conf->accessControl.userTokenPoliciesSize;
+
+ UA_String_copy(&localCertificate, &endpoint->endpointDescription.serverCertificate);
+ UA_ApplicationDescription_copy(&conf->applicationDescription,
+ &endpoint->endpointDescription.server);
+
+ return UA_STATUSCODE_GOOD;
+}
+
+static UA_StatusCode
+createSecurityPolicyBasic256Sha256Endpoint(UA_ServerConfig *const conf,
+ UA_Endpoint *endpoint,
+ UA_MessageSecurityMode securityMode,
+ const UA_ByteString localCertificate,
+ const UA_ByteString localPrivateKey) {
+ UA_EndpointDescription_init(&endpoint->endpointDescription);
+
+ UA_StatusCode retval =
+ UA_SecurityPolicy_Basic256Sha256(&endpoint->securityPolicy, &conf->certificateVerification, localCertificate,
+ localPrivateKey, conf->logger);
+ if(retval != UA_STATUSCODE_GOOD) {
+ endpoint->securityPolicy.deleteMembers(&endpoint->securityPolicy);
+ return retval;
+ }
+
+ endpoint->endpointDescription.securityMode = securityMode;
+ endpoint->endpointDescription.securityPolicyUri =
+ UA_STRING_ALLOC("http://opcfoundation.org/UA/SecurityPolicy#Basic256Sha256");
+ endpoint->endpointDescription.transportProfileUri =
+ UA_STRING_ALLOC("http://opcfoundation.org/UA-Profile/Transport/uatcp-uasc-uabinary");
+
+ /* Enable all login mechanisms from the access control plugin */
+ retval = UA_Array_copy(conf->accessControl.userTokenPolicies,
+ conf->accessControl.userTokenPoliciesSize,
+ (void **)&endpoint->endpointDescription.userIdentityTokens,
+ &UA_TYPES[UA_TYPES_USERTOKENPOLICY]);
+ if(retval != UA_STATUSCODE_GOOD)
+ return retval;
+ endpoint->endpointDescription.userIdentityTokensSize =
+ conf->accessControl.userTokenPoliciesSize;
+
+ UA_String_copy(&localCertificate, &endpoint->endpointDescription.serverCertificate);
+ UA_ApplicationDescription_copy(&conf->applicationDescription,
+ &endpoint->endpointDescription.server);
+
+ return UA_STATUSCODE_GOOD;
+}
+
+#endif
+
+const size_t usernamePasswordsSize = 2;
+UA_UsernamePasswordLogin usernamePasswords[2] = {
+ {UA_STRING_STATIC("user1"), UA_STRING_STATIC("password")},
+ {UA_STRING_STATIC("user2"), UA_STRING_STATIC("password1")}};
+
+static UA_ServerConfig *
+createDefaultConfig(void) {
+ UA_ServerConfig *conf = (UA_ServerConfig *)UA_malloc(sizeof(UA_ServerConfig));
+ if(!conf)
+ return NULL;
+
+ /* Zero out.. All members have a valid initial value */
+ memset(conf, 0, sizeof(UA_ServerConfig));
+
+ /* --> Start setting the default static config <-- */
+ conf->nThreads = 1;
+ conf->logger = UA_Log_Stdout;
+
+ /* Server Description */
+ 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));
+ conf->buildInfo.buildNumber = UA_STRING_ALLOC(__DATE__
+ " "
+ __TIME__);
+ conf->buildInfo.buildDate = 0;
+
+ conf->applicationDescription.applicationUri = UA_STRING_ALLOC(APPLICATION_URI);
+ 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; */
+
+#ifdef UA_ENABLE_DISCOVERY
+ /* conf->mdnsServerName = UA_STRING_NULL; */
+ /* conf->serverCapabilitiesSize = 0; */
+ /* conf->serverCapabilities = NULL; */
+#endif
+
+ /* Custom DataTypes */
+ /* conf->customDataTypesSize = 0; */
+ /* conf->customDataTypes = NULL; */
+
+ /* Networking */
+ /* conf->networkLayersSize = 0; */
+ /* conf->networkLayers = NULL; */
+ /* conf->customHostname = UA_STRING_NULL; */
+
+ /* Endpoints */
+ /* conf->endpoints = {0, NULL}; */
+
+ /* Certificate Verification that accepts every certificate. Can be
+ * overwritten when the policy is specialized. */
+ UA_CertificateVerification_AcceptAll(&conf->certificateVerification);
+
+ /* Global Node Lifecycle */
+ conf->nodeLifecycle.constructor = NULL;
+ conf->nodeLifecycle.destructor = NULL;
+
+ /* Access Control. Anonymous Login only. */
+ conf->accessControl = UA_AccessControl_default(true, usernamePasswordsSize, usernamePasswords);
+
+ /* Limits for SecureChannels */
+ conf->maxSecureChannels = 40;
+ conf->maxSecurityTokenLifetime = 10 * 60 * 1000; /* 10 minutes */
+
+ /* Limits for Sessions */
+ conf->maxSessions = 100;
+ conf->maxSessionTimeout = 60.0 * 60.0 * 1000.0; /* 1h */
+
+ /* 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->maxRetransmissionQueueSize = 0; /* unlimited */
+
+ /* Limits for MonitoredItems */
+ conf->samplingIntervalLimits = UA_DURATIONRANGE(50.0, 24.0 * 3600.0 * 1000.0);
+ conf->queueSizeLimits = UA_UINT32RANGE(1, 100);
+
+#ifdef UA_ENABLE_DISCOVERY
+ conf->discoveryCleanupTimeout = 60 * 60;
+#endif
+
+ /* --> Finish setting the default static config <-- */
+
+ return conf;
+}
+
+static UA_StatusCode
+addDefaultNetworkLayers(UA_ServerConfig *conf, UA_UInt16 portNumber) {
+ /* Add a network layer */
+ conf->networkLayers = (UA_ServerNetworkLayer *)
+ UA_malloc(sizeof(UA_ServerNetworkLayer));
+ if(!conf->networkLayers)
+ return UA_STATUSCODE_BADOUTOFMEMORY;
+
+ conf->networkLayers[0] =
+ UA_ServerNetworkLayerTCP(UA_ConnectionConfig_default, portNumber, conf->logger);
+ if (!conf->networkLayers[0].handle)
+ return UA_STATUSCODE_BADOUTOFMEMORY;
+ conf->networkLayersSize = 1;
+
+ return UA_STATUSCODE_GOOD;
+}
+
+UA_ServerConfig *
+UA_ServerConfig_new_minimal(UA_UInt16 portNumber,
+ const UA_ByteString *certificate) {
+ UA_ServerConfig *conf = createDefaultConfig();
+
+ UA_StatusCode retval = UA_Nodestore_default_new(&conf->nodestore);
+ if(retval != UA_STATUSCODE_GOOD) {
+ UA_ServerConfig_delete(conf);
+ return NULL;
+ }
+
+ if(addDefaultNetworkLayers(conf, portNumber) != UA_STATUSCODE_GOOD) {
+ UA_ServerConfig_delete(conf);
+ return NULL;
+ }
+
+ /* Allocate the endpoint */
+ conf->endpoints = (UA_Endpoint *)UA_malloc(sizeof(UA_Endpoint));
+ if(!conf->endpoints) {
+ UA_ServerConfig_delete(conf);
+ return NULL;
+ }
+ conf->endpointsSize = 1;
+
+ /* Populate the endpoint */
+ UA_ByteString localCertificate = UA_BYTESTRING_NULL;
+ if(certificate)
+ localCertificate = *certificate;
+ retval =
+ createSecurityPolicyNoneEndpoint(conf, &conf->endpoints[0], localCertificate);
+ if(retval != UA_STATUSCODE_GOOD) {
+ UA_ServerConfig_delete(conf);
+ return NULL;
+ }
+
+ return conf;
+}
+
+#ifdef UA_ENABLE_ENCRYPTION
+
+UA_ServerConfig *
+UA_ServerConfig_new_basic128rsa15(UA_UInt16 portNumber,
+ const UA_ByteString *certificate,
+ const UA_ByteString *privateKey,
+ const UA_ByteString *trustList,
+ size_t trustListSize,
+ const UA_ByteString *revocationList,
+ size_t revocationListSize) {
+ UA_ServerConfig *conf = createDefaultConfig();
+
+ UA_StatusCode retval = UA_CertificateVerification_Trustlist(&conf->certificateVerification,
+ trustList, trustListSize,
+ revocationList, revocationListSize);
+ if(retval != UA_STATUSCODE_GOOD) {
+ UA_ServerConfig_delete(conf);
+ return NULL;
+ }
+
+ retval = UA_Nodestore_default_new(&conf->nodestore);
+ if(retval != UA_STATUSCODE_GOOD) {
+ UA_ServerConfig_delete(conf);
+ return NULL;
+ }
+
+ if(addDefaultNetworkLayers(conf, portNumber) != UA_STATUSCODE_GOOD) {
+ UA_ServerConfig_delete(conf);
+ return NULL;
+ }
+
+ if(trustListSize == 0)
+ UA_LOG_WARNING(UA_Log_Stdout, UA_LOGCATEGORY_USERLAND,
+ "No CA trust-list provided. Any remote certificate will be accepted.");
+
+ /* Allocate the endpoints */
+ conf->endpointsSize = 0;
+ conf->endpoints = (UA_Endpoint *)UA_malloc(sizeof(UA_Endpoint) * 3);
+ if(!conf->endpoints) {
+ UA_ServerConfig_delete(conf);
+ return NULL;
+ }
+
+ /* Populate the endpoints */
+ ++conf->endpointsSize;
+ retval = createSecurityPolicyNoneEndpoint(conf, &conf->endpoints[0], *certificate);
+ if(retval != UA_STATUSCODE_GOOD) {
+ UA_ServerConfig_delete(conf);
+ return NULL;
+ }
+
+ ++conf->endpointsSize;
+ retval = createSecurityPolicyBasic128Rsa15Endpoint(conf, &conf->endpoints[1],
+ UA_MESSAGESECURITYMODE_SIGN, *certificate,
+ *privateKey);
+ if(retval != UA_STATUSCODE_GOOD) {
+ UA_ServerConfig_delete(conf);
+ return NULL;
+ }
+
+ ++conf->endpointsSize;
+ retval = createSecurityPolicyBasic128Rsa15Endpoint(conf, &conf->endpoints[2],
+ UA_MESSAGESECURITYMODE_SIGNANDENCRYPT, *certificate,
+ *privateKey);
+ if(retval != UA_STATUSCODE_GOOD) {
+ UA_ServerConfig_delete(conf);
+ return NULL;
+ }
+
+ return conf;
+}
+
+UA_ServerConfig *
+UA_ServerConfig_new_basic256sha256(UA_UInt16 portNumber,
+ const UA_ByteString *certificate,
+ const UA_ByteString *privateKey,
+ const UA_ByteString *trustList,
+ size_t trustListSize,
+ const UA_ByteString *revocationList,
+ size_t revocationListSize) {
+ UA_ServerConfig *conf = createDefaultConfig();
+
+ UA_StatusCode retval = UA_CertificateVerification_Trustlist(&conf->certificateVerification,
+ trustList, trustListSize,
+ revocationList, revocationListSize);
+ if(retval != UA_STATUSCODE_GOOD) {
+ UA_ServerConfig_delete(conf);
+ return NULL;
+ }
+
+ retval = UA_Nodestore_default_new(&conf->nodestore);
+ if(retval != UA_STATUSCODE_GOOD) {
+ UA_ServerConfig_delete(conf);
+ return NULL;
+ }
+
+ if(addDefaultNetworkLayers(conf, portNumber) != UA_STATUSCODE_GOOD) {
+ UA_ServerConfig_delete(conf);
+ return NULL;
+ }
+
+ if(trustListSize == 0)
+ UA_LOG_WARNING(UA_Log_Stdout, UA_LOGCATEGORY_USERLAND,
+ "No CA trust-list provided. Any remote certificate will be accepted.");
+
+ /* Allocate the endpoints */
+ conf->endpointsSize = 0;
+ conf->endpoints = (UA_Endpoint *)UA_malloc(sizeof(UA_Endpoint) * 3);
+ if(!conf->endpoints) {
+ UA_ServerConfig_delete(conf);
+ return NULL;
+ }
+
+ /* Populate the endpoints */
+ ++conf->endpointsSize;
+ retval = createSecurityPolicyNoneEndpoint(conf, &conf->endpoints[0], *certificate);
+ if(retval != UA_STATUSCODE_GOOD) {
+ UA_ServerConfig_delete(conf);
+ return NULL;
+ }
+
+ ++conf->endpointsSize;
+ retval = createSecurityPolicyBasic256Sha256Endpoint(conf, &conf->endpoints[1],
+ UA_MESSAGESECURITYMODE_SIGN, *certificate,
+ *privateKey);
+ if(retval != UA_STATUSCODE_GOOD) {
+ UA_ServerConfig_delete(conf);
+ return NULL;
+ }
+
+ ++conf->endpointsSize;
+ retval = createSecurityPolicyBasic256Sha256Endpoint(conf, &conf->endpoints[2],
+ UA_MESSAGESECURITYMODE_SIGNANDENCRYPT, *certificate,
+ *privateKey);
+ if(retval != UA_STATUSCODE_GOOD) {
+ UA_ServerConfig_delete(conf);
+ return NULL;
+ }
+
+ return conf;
+}
+
+UA_ServerConfig *
+UA_ServerConfig_new_allSecurityPolicies(UA_UInt16 portNumber,
+ const UA_ByteString *certificate,
+ const UA_ByteString *privateKey,
+ const UA_ByteString *trustList,
+ size_t trustListSize,
+ const UA_ByteString *revocationList,
+ size_t revocationListSize) {
+ UA_ServerConfig *conf = createDefaultConfig();
+
+ UA_StatusCode retval = UA_CertificateVerification_Trustlist(&conf->certificateVerification,
+ trustList, trustListSize,
+ revocationList, revocationListSize);
+ if(retval != UA_STATUSCODE_GOOD) {
+ UA_ServerConfig_delete(conf);
+ return NULL;
+ }
+
+ retval = UA_Nodestore_default_new(&conf->nodestore);
+ if(retval != UA_STATUSCODE_GOOD) {
+ UA_ServerConfig_delete(conf);
+ return NULL;
+ }
+
+ if(addDefaultNetworkLayers(conf, portNumber) != UA_STATUSCODE_GOOD) {
+ UA_ServerConfig_delete(conf);
+ return NULL;
+ }
+
+ if(trustListSize == 0)
+ UA_LOG_WARNING(UA_Log_Stdout, UA_LOGCATEGORY_USERLAND,
+ "No CA trust-list provided. Any remote certificate will be accepted.");
+
+ /* Allocate the endpoints */
+ conf->endpointsSize = 0;
+ conf->endpoints = (UA_Endpoint *)UA_malloc(sizeof(UA_Endpoint) * 5);
+ if(!conf->endpoints) {
+ UA_ServerConfig_delete(conf);
+ return NULL;
+ }
+
+ /* Populate the endpoints */
+ retval = createSecurityPolicyNoneEndpoint(conf, &conf->endpoints[conf->endpointsSize], *certificate);
+ ++conf->endpointsSize;
+ if(retval != UA_STATUSCODE_GOOD) {
+ UA_ServerConfig_delete(conf);
+ return NULL;
+ }
+
+ retval = createSecurityPolicyBasic128Rsa15Endpoint(conf, &conf->endpoints[conf->endpointsSize],
+ UA_MESSAGESECURITYMODE_SIGN, *certificate,
+ *privateKey);
+ ++conf->endpointsSize;
+ if(retval != UA_STATUSCODE_GOOD) {
+ UA_ServerConfig_delete(conf);
+ return NULL;
+ }
+
+ retval = createSecurityPolicyBasic128Rsa15Endpoint(conf, &conf->endpoints[conf->endpointsSize],
+ UA_MESSAGESECURITYMODE_SIGNANDENCRYPT, *certificate,
+ *privateKey);
+ ++conf->endpointsSize;
+ if(retval != UA_STATUSCODE_GOOD) {
+ UA_ServerConfig_delete(conf);
+ return NULL;
+ }
+
+ retval = createSecurityPolicyBasic256Sha256Endpoint(conf, &conf->endpoints[conf->endpointsSize],
+ UA_MESSAGESECURITYMODE_SIGN, *certificate,
+ *privateKey);
+ ++conf->endpointsSize;
+ if(retval != UA_STATUSCODE_GOOD) {
+ UA_ServerConfig_delete(conf);
+ return NULL;
+ }
+
+ retval = createSecurityPolicyBasic256Sha256Endpoint(conf, &conf->endpoints[conf->endpointsSize],
+ UA_MESSAGESECURITYMODE_SIGNANDENCRYPT, *certificate,
+ *privateKey);
+ ++conf->endpointsSize;
+ if(retval != UA_STATUSCODE_GOOD) {
+ UA_ServerConfig_delete(conf);
+ return NULL;
+ }
+
+ return conf;
+}
+
+
+#endif
+
+void
+UA_ServerConfig_delete(UA_ServerConfig *config) {
+ if(!config)
+ return;
+
+ /* Server Description */
+ UA_BuildInfo_deleteMembers(&config->buildInfo);
+ UA_ApplicationDescription_deleteMembers(&config->applicationDescription);
+#ifdef UA_ENABLE_DISCOVERY
+ UA_String_deleteMembers(&config->mdnsServerName);
+ UA_Array_delete(config->serverCapabilities, config->serverCapabilitiesSize,
+ &UA_TYPES[UA_TYPES_STRING]);
+ config->serverCapabilities = NULL;
+ config->serverCapabilitiesSize = 0;
+#endif
+
+ /* Nodestore */
+ if(config->nodestore.deleteNodestore)
+ config->nodestore.deleteNodestore(config->nodestore.context);
+
+ /* Custom DataTypes */
+ for(size_t i = 0; i < config->customDataTypesSize; ++i)
+ UA_free(config->customDataTypes[i].members);
+ UA_free(config->customDataTypes);
+ config->customDataTypes = NULL;
+ config->customDataTypesSize = 0;
+
+ /* Networking */
+ for(size_t i = 0; i < config->networkLayersSize; ++i)
+ config->networkLayers[i].deleteMembers(&config->networkLayers[i]);
+ UA_free(config->networkLayers);
+ config->networkLayers = NULL;
+ config->networkLayersSize = 0;
+ UA_String_deleteMembers(&config->customHostname);
+ config->customHostname = UA_STRING_NULL;
+
+ for(size_t i = 0; i < config->endpointsSize; ++i) {
+ UA_SecurityPolicy *policy = &config->endpoints[i].securityPolicy;
+ policy->deleteMembers(policy);
+ UA_EndpointDescription_deleteMembers(&config->endpoints[i].endpointDescription);
+ }
+ UA_free(config->endpoints);
+ config->endpoints = NULL;
+ config->endpointsSize = 0;
+
+ /* Certificate Validation */
+ config->certificateVerification.deleteMembers(&config->certificateVerification);
+
+ /* Access Control */
+ config->accessControl.deleteMembers(&config->accessControl);
+
+ UA_free(config);
+}
+
+/***************************/
+/* Default Client Settings */
+/***************************/
+
+const UA_ClientConfig UA_ClientConfig_default = {
+ 5000, /* .timeout, 5 seconds */
+ 10 * 60 * 1000, /* .secureChannelLifeTime, 10 minutes */
+ UA_Log_Stdout, /* .logger */
+ { /* .localConnectionConfig */
+ 0, /* .protocolVersion */
+ 65535, /* .sendBufferSize, 64k per chunk */
+ 65535, /* .recvBufferSize, 64k per chunk */
+ 0, /* .maxMessageSize, 0 -> unlimited */
+ 0 /* .maxChunkCount, 0 -> unlimited */
+ },
+ UA_ClientConnectionTCP, /* .connectionFunc */
+
+ 0, /* .customDataTypesSize */
+ NULL, /*.customDataTypes */
+
+ NULL, /*.stateCallback */
+#ifdef UA_ENABLE_SUBSCRIPTIONS
+ NULL, /*.subscriptionInactivityCallback */
+#endif
+ NULL, /*.inactivityCallback */
+ NULL, /*.clientContext */
+#ifdef UA_ENABLE_SUBSCRIPTIONS
+ 10, /* .outStandingPublishRequests */
+#endif
+ 0 /* .connectivityCheckInterval */
+};
+
+UA_ClientConfig UA_Server_getClientConfig(void)
+{
+ return UA_ClientConfig_default;
+}
+
+/*********************************** amalgamated original file "/home/jvoe/open62541/plugins/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
+ */
+
+
+static UA_StatusCode
+verify_none(const UA_SecurityPolicy *securityPolicy,
+ void *channelContext,
+ const UA_ByteString *message,
+ const UA_ByteString *signature) {
+ return UA_STATUSCODE_GOOD;
+}
+
+static UA_StatusCode
+sign_none(const UA_SecurityPolicy *securityPolicy,
+ void *channelContext,
+ const UA_ByteString *message,
+ UA_ByteString *signature) {
+ return UA_STATUSCODE_GOOD;
+}
+
+static size_t
+length_none(const UA_SecurityPolicy *securityPolicy,
+ const void *channelContext) {
+ return 0;
+}
+
+static UA_StatusCode
+encrypt_none(const UA_SecurityPolicy *securityPolicy,
+ void *channelContext,
+ UA_ByteString *data) {
+ return UA_STATUSCODE_GOOD;
+}
+
+static UA_StatusCode
+decrypt_none(const UA_SecurityPolicy *securityPolicy,
+ 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(const UA_SecurityPolicy *securityPolicy,
+ 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(const UA_SecurityPolicy *securityPolicy, UA_ByteString *out) {
+ if(securityPolicy == NULL || out == NULL)
+ return UA_STATUSCODE_BADINTERNALERROR;
+
+ /* Fill blocks of four byte */
+ size_t i = 0;
+ while(i + 3 < out->length) {
+ UA_UInt32 rand = UA_UInt32_random();
+ memcpy(&out->data[i], &rand, 4);
+ i = i+4;
+ }
+
+ /* Fill the remaining byte */
+ UA_UInt32 rand = UA_UInt32_random();
+ memcpy(&out->data[i], &rand, out->length % 4);
+
+ return UA_STATUSCODE_GOOD;
+}
+
+static UA_StatusCode
+newContext_none(const UA_SecurityPolicy *securityPolicy,
+ const UA_ByteString *remoteCertificate,
+ void **channelContext) {
+ return UA_STATUSCODE_GOOD;
+}
+
+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 void
+policy_deletemembers_none(UA_SecurityPolicy *policy) {
+ UA_ByteString_deleteMembers(&policy->localCertificate);
+}
+
+UA_StatusCode
+UA_SecurityPolicy_None(UA_SecurityPolicy *policy, UA_CertificateVerification *certificateVerification,
+ const UA_ByteString localCertificate, UA_Logger logger) {
+ policy->policyContext = (void *)(uintptr_t)logger;
+ policy->policyUri = UA_STRING("http://opcfoundation.org/UA/SecurityPolicy#None");
+ policy->logger = logger;
+ UA_ByteString_copy(&localCertificate, &policy->localCertificate);
+
+ policy->certificateVerification = certificateVerification;
+
+ policy->symmetricModule.generateKey = generateKey_none;
+ policy->symmetricModule.generateNonce = generateNonce_none;
+
+ 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;
+
+ UA_SecurityPolicyEncryptionAlgorithm *sym_encryptionAlgorithm =
+ &policy->symmetricModule.cryptoModule.encryptionAlgorithm;
+ 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;
+
+ 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->deleteMembers = policy_deletemembers_none;
+
+ return UA_STATUSCODE_GOOD;
+}
+
+/*********************************** amalgamated original file "/home/jvoe/open62541/plugins/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
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * Copyright 2018 (c) Mark Giraud, Fraunhofer IOSB
+ */
+
+
+#ifdef UA_ENABLE_ENCRYPTION
+
+#include <mbedtls/aes.h>
+#include <mbedtls/md.h>
+#include <mbedtls/x509_crt.h>
+#include <mbedtls/ctr_drbg.h>
+#include <mbedtls/entropy.h>
+#include <mbedtls/entropy_poll.h>
+#include <mbedtls/error.h>
+#include <mbedtls/version.h>
+#include <mbedtls/sha1.h>
+
+
+/* Notes:
+ * mbedTLS' AES allows in-place encryption and decryption. Sow we don't have to
+ * allocate temp buffers.
+ * https://tls.mbed.org/discussions/generic/in-place-decryption-with-aes256-same-input-output-buffer
+ */
+
+#define UA_SECURITYPOLICY_BASIC128RSA15_RSAPADDING_LEN 11
+#define UA_SHA1_LENGTH 20
+#define UA_SECURITYPOLICY_BASIC128RSA15_SYM_KEY_LENGTH 16
+#define UA_BASIC128RSA15_SYM_SIGNING_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_MINASYMKEYLENGTH 128
+#define UA_SECURITYPOLICY_BASIC128RSA15_MAXASYMKEYLENGTH 256
+
+#define UA_LOG_MBEDERR \
+ char errBuff[300]; \
+ mbedtls_strerror(mbedErr, errBuff, 300); \
+ UA_LOG_WARNING(securityPolicy->logger, UA_LOGCATEGORY_SECURITYPOLICY, \
+ "mbedTLS returned an error: %s", errBuff); \
+
+#define UA_MBEDTLS_ERRORHANDLING(errorcode) \
+ if(mbedErr) { \
+ UA_LOG_MBEDERR \
+ retval = errorcode; \
+ }
+
+#define UA_MBEDTLS_ERRORHANDLING_RETURN(errorcode) \
+ if(mbedErr) { \
+ UA_LOG_MBEDERR \
+ return errorcode; \
+ }
+
+typedef struct {
+ const UA_SecurityPolicy *securityPolicy;
+ UA_ByteString localCertThumbprint;
+
+ mbedtls_ctr_drbg_context drbgContext;
+ mbedtls_entropy_context entropyContext;
+ mbedtls_md_context_t sha1MdContext;
+ mbedtls_pk_context localPrivateKey;
+} Basic128Rsa15_PolicyContext;
+
+typedef struct {
+ Basic128Rsa15_PolicyContext *policyContext;
+
+ UA_ByteString localSymSigningKey;
+ UA_ByteString localSymEncryptingKey;
+ UA_ByteString localSymIv;
+
+ UA_ByteString remoteSymSigningKey;
+ UA_ByteString remoteSymEncryptingKey;
+ UA_ByteString remoteSymIv;
+
+ mbedtls_x509_crt remoteCertificate;
+} Basic128Rsa15_ChannelContext;
+
+
+/********************/
+/* AsymmetricModule */
+/********************/
+
+static UA_StatusCode
+asym_verify_sp_basic128rsa15(const UA_SecurityPolicy *securityPolicy,
+ Basic128Rsa15_ChannelContext *cc,
+ const UA_ByteString *message,
+ const UA_ByteString *signature) {
+ if(securityPolicy == NULL || message == NULL || signature == NULL || cc == NULL)
+ return UA_STATUSCODE_BADINTERNALERROR;
+
+ /* 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
+
+ /* Set the RSA settings */
+ mbedtls_rsa_context *rsaContext = mbedtls_pk_rsa(cc->remoteCertificate.pk);
+ mbedtls_rsa_set_padding(rsaContext, MBEDTLS_RSA_PKCS_V15, 0);
+
+ /* Verify */
+ int mbedErr = mbedtls_pk_verify(&cc->remoteCertificate.pk,
+ MBEDTLS_MD_SHA1, hash, UA_SHA1_LENGTH,
+ signature->data, signature->length);
+ UA_MBEDTLS_ERRORHANDLING_RETURN(UA_STATUSCODE_BADSECURITYCHECKSFAILED);
+ return UA_STATUSCODE_GOOD;
+}
+
+static UA_StatusCode
+asym_sign_sp_basic128rsa15(const UA_SecurityPolicy *securityPolicy,
+ Basic128Rsa15_ChannelContext *cc,
+ const UA_ByteString *message,
+ UA_ByteString *signature) {
+ if(securityPolicy == NULL || message == NULL || signature == NULL || cc == NULL)
+ return UA_STATUSCODE_BADINTERNALERROR;
+
+ 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
+
+ Basic128Rsa15_PolicyContext *pc = cc->policyContext;
+ mbedtls_rsa_context *rsaContext = mbedtls_pk_rsa(pc->localPrivateKey);
+ mbedtls_rsa_set_padding(rsaContext, MBEDTLS_RSA_PKCS_V15, 0);
+
+ size_t sigLen = 0;
+ int mbedErr = mbedtls_pk_sign(&pc->localPrivateKey,
+ MBEDTLS_MD_SHA1, hash,
+ UA_SHA1_LENGTH, signature->data,
+ &sigLen, mbedtls_ctr_drbg_random,
+ &pc->drbgContext);
+ UA_MBEDTLS_ERRORHANDLING_RETURN(UA_STATUSCODE_BADINTERNALERROR);
+ return UA_STATUSCODE_GOOD;
+}
+
+static size_t
+asym_getLocalSignatureSize_sp_basic128rsa15(const UA_SecurityPolicy *securityPolicy,
+ const Basic128Rsa15_ChannelContext *cc) {
+ if(securityPolicy == NULL || cc == NULL)
+ return 0;
+
+ return mbedtls_pk_rsa(cc->policyContext->localPrivateKey)->len;
+}
+
+static size_t
+asym_getRemoteSignatureSize_sp_basic128rsa15(const UA_SecurityPolicy *securityPolicy,
+ const Basic128Rsa15_ChannelContext *cc) {
+ if(securityPolicy == NULL || cc == NULL)
+ return 0;
+
+ return mbedtls_pk_rsa(cc->remoteCertificate.pk)->len;
+}
+
+static UA_StatusCode
+asym_encrypt_sp_basic128rsa15(const UA_SecurityPolicy *securityPolicy,
+ Basic128Rsa15_ChannelContext *cc,
+ UA_ByteString *data) {
+ if(securityPolicy == NULL || cc == NULL || data == NULL)
+ return UA_STATUSCODE_BADINTERNALERROR;
+
+ const size_t plainTextBlockSize = securityPolicy->asymmetricModule.cryptoModule.encryptionAlgorithm.
+ getRemotePlainTextBlockSize(securityPolicy, cc);
+
+ 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);
+
+ 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(retval != UA_STATUSCODE_GOOD)
+ return retval;
+
+ size_t lenDataToEncrypt = data->length;
+ size_t inOffset = 0;
+ size_t offset = 0;
+ size_t outLength = 0;
+ Basic128Rsa15_PolicyContext *pc = cc->policyContext;
+ while(lenDataToEncrypt >= plainTextBlockSize) {
+ int mbedErr = mbedtls_pk_encrypt(&cc->remoteCertificate.pk,
+ data->data + inOffset, plainTextBlockSize,
+ encrypted.data + offset, &outLength,
+ encrypted.length - offset,
+ mbedtls_ctr_drbg_random,
+ &pc->drbgContext);
+ UA_MBEDTLS_ERRORHANDLING(UA_STATUSCODE_BADINTERNALERROR);
+ if(retval != UA_STATUSCODE_GOOD) {
+ UA_ByteString_deleteMembers(&encrypted);
+ return retval;
+ }
+
+ inOffset += plainTextBlockSize;
+ offset += outLength;
+ lenDataToEncrypt -= plainTextBlockSize;
+ }
+
+ memcpy(data->data, encrypted.data, offset);
+ UA_ByteString_deleteMembers(&encrypted);
+
+ return UA_STATUSCODE_GOOD;
+}
+
+static UA_StatusCode
+asym_decrypt_sp_basic128rsa15(const UA_SecurityPolicy *securityPolicy,
+ Basic128Rsa15_ChannelContext *cc,
+ UA_ByteString *data) {
+ if(securityPolicy == NULL || 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);
+
+ if(data->length % rsaContext->len != 0)
+ return UA_STATUSCODE_BADINTERNALERROR;
+
+ UA_ByteString decrypted;
+ UA_StatusCode retval = UA_ByteString_allocBuffer(&decrypted, data->length);
+ if(retval != UA_STATUSCODE_GOOD)
+ return retval;
+
+ size_t lenDataToDecrypt = data->length;
+ size_t inOffset = 0;
+ size_t offset = 0;
+ size_t outLength = 0;
+ while(lenDataToDecrypt >= rsaContext->len) {
+ int mbedErr = mbedtls_pk_decrypt(&cc->policyContext->localPrivateKey,
+ data->data + inOffset, rsaContext->len,
+ decrypted.data + offset, &outLength,
+ decrypted.length - offset, NULL, NULL);
+ if(mbedErr)
+ UA_ByteString_deleteMembers(&decrypted); // TODO: Maybe change error macro to jump to cleanup?
+ UA_MBEDTLS_ERRORHANDLING_RETURN(UA_STATUSCODE_BADSECURITYCHECKSFAILED);
+
+ inOffset += rsaContext->len;
+ offset += outLength;
+ lenDataToDecrypt -= rsaContext->len;
+ }
+
+ if(lenDataToDecrypt == 0) {
+ memcpy(data->data, decrypted.data, offset);
+ data->length = offset;
+ } else {
+ retval = UA_STATUSCODE_BADINTERNALERROR;
+ }
+
+ UA_ByteString_deleteMembers(&decrypted);
+ return retval;
+}
+
+static size_t
+asym_getRemoteEncryptionKeyLength_sp_basic128rsa15(const UA_SecurityPolicy *securityPolicy,
+ 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) {
+ mbedtls_rsa_context *const rsaContext = mbedtls_pk_rsa(cc->remoteCertificate.pk);
+ return rsaContext->len;
+}
+
+static size_t
+asym_getRemotePlainTextBlockSize_sp_basic128rsa15(const UA_SecurityPolicy *securityPolicy,
+ const Basic128Rsa15_ChannelContext *cc) {
+ mbedtls_rsa_context *const rsaContext = mbedtls_pk_rsa(cc->remoteCertificate.pk);
+ return rsaContext->len - UA_SECURITYPOLICY_BASIC128RSA15_RSAPADDING_LEN;
+}
+
+static UA_StatusCode
+asym_makeThumbprint_sp_basic128rsa15(const UA_SecurityPolicy *securityPolicy,
+ const UA_ByteString *certificate,
+ UA_ByteString *thumbprint) {
+ if(securityPolicy == NULL || certificate == NULL || thumbprint == NULL)
+ return UA_STATUSCODE_BADINTERNALERROR;
+
+ if(UA_ByteString_equal(certificate, &UA_BYTESTRING_NULL))
+ return UA_STATUSCODE_BADINTERNALERROR;
+
+ if(thumbprint->length != UA_SHA1_LENGTH)
+ return UA_STATUSCODE_BADINTERNALERROR;
+
+#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;
+}
+
+static UA_StatusCode
+asymmetricModule_compareCertificateThumbprint_sp_basic128rsa15(const UA_SecurityPolicy *securityPolicy,
+ const UA_ByteString *certificateThumbprint) {
+ if(securityPolicy == NULL || certificateThumbprint == NULL)
+ return UA_STATUSCODE_BADINTERNALERROR;
+
+ Basic128Rsa15_PolicyContext *pc = (Basic128Rsa15_PolicyContext *)securityPolicy->policyContext;
+ if(!UA_ByteString_equal(certificateThumbprint, &pc->localCertThumbprint))
+ return UA_STATUSCODE_BADCERTIFICATEINVALID;
+
+ return UA_STATUSCODE_GOOD;
+}
+
+/*******************/
+/* SymmetricModule */
+/*******************/
+
+static void
+md_hmac(mbedtls_md_context_t *context, const UA_ByteString *key,
+ const UA_ByteString *in, unsigned char out[20]) {
+ 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 UA_StatusCode
+sym_verify_sp_basic128rsa15(const UA_SecurityPolicy *securityPolicy,
+ Basic128Rsa15_ChannelContext *cc,
+ const UA_ByteString *message,
+ const UA_ByteString *signature) {
+ if(securityPolicy == NULL || 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");
+ return UA_STATUSCODE_BADSECURITYCHECKSFAILED;
+ }
+
+ Basic128Rsa15_PolicyContext *pc =
+ (Basic128Rsa15_PolicyContext *)securityPolicy->policyContext;
+
+ unsigned char mac[UA_SHA1_LENGTH];
+ md_hmac(&pc->sha1MdContext, &cc->remoteSymSigningKey, message, mac);
+
+ /* Compare with Signature */
+ if(memcmp(signature->data, mac, UA_SHA1_LENGTH) != 0)
+ return UA_STATUSCODE_BADSECURITYCHECKSFAILED;
+ return UA_STATUSCODE_GOOD;
+}
+
+static UA_StatusCode
+sym_sign_sp_basic128rsa15(const UA_SecurityPolicy *securityPolicy,
+ const Basic128Rsa15_ChannelContext *cc,
+ const UA_ByteString *message,
+ UA_ByteString *signature) {
+ if(signature->length != UA_SHA1_LENGTH)
+ return UA_STATUSCODE_BADINTERNALERROR;
+
+ md_hmac(&cc->policyContext->sha1MdContext, &cc->localSymSigningKey,
+ message, signature->data);
+ return UA_STATUSCODE_GOOD;
+}
+
+static size_t
+sym_getSignatureSize_sp_basic128rsa15(const UA_SecurityPolicy *securityPolicy,
+ const void *channelContext) {
+ return UA_SHA1_LENGTH;
+}
+
+static size_t
+sym_getSigningKeyLength_sp_basic128rsa15(const UA_SecurityPolicy *const securityPolicy,
+ 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) {
+ return UA_SECURITYPOLICY_BASIC128RSA15_SYM_KEY_LENGTH;
+}
+
+static size_t
+sym_getEncryptionBlockSize_sp_basic128rsa15(const UA_SecurityPolicy *const securityPolicy,
+ 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) {
+ return UA_SECURITYPOLICY_BASIC128RSA15_SYM_PLAIN_TEXT_BLOCK_SIZE;
+}
+
+static UA_StatusCode
+sym_encrypt_sp_basic128rsa15(const UA_SecurityPolicy *securityPolicy,
+ const Basic128Rsa15_ChannelContext *cc,
+ UA_ByteString *data) {
+ if(securityPolicy == NULL || cc == NULL || data == NULL)
+ return UA_STATUSCODE_BADINTERNALERROR;
+
+ if(cc->localSymIv.length !=
+ securityPolicy->symmetricModule.cryptoModule.encryptionAlgorithm.getLocalBlockSize(securityPolicy, cc))
+ 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.");
+ return UA_STATUSCODE_BADINTERNALERROR;
+ }
+
+ /* 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);
+ UA_MBEDTLS_ERRORHANDLING_RETURN(UA_STATUSCODE_BADINTERNALERROR);
+
+ 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);
+ UA_MBEDTLS_ERRORHANDLING(UA_STATUSCODE_BADINTERNALERROR);
+ UA_ByteString_deleteMembers(&ivCopy);
+ return retval;
+}
+
+static UA_StatusCode
+sym_decrypt_sp_basic128rsa15(const UA_SecurityPolicy *securityPolicy,
+ const Basic128Rsa15_ChannelContext *cc,
+ UA_ByteString *data) {
+ if(securityPolicy == NULL || cc == NULL || data == NULL)
+ return UA_STATUSCODE_BADINTERNALERROR;
+
+ size_t encryptionBlockSize =
+ securityPolicy->symmetricModule.cryptoModule.encryptionAlgorithm.getLocalBlockSize(securityPolicy, cc);
+
+ 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.");
+ 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);
+ UA_MBEDTLS_ERRORHANDLING_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);
+ UA_MBEDTLS_ERRORHANDLING(UA_STATUSCODE_BADINTERNALERROR);
+ UA_ByteString_deleteMembers(&ivCopy);
+ return retval;
+}
+
+static void
+swapBuffers(UA_ByteString *const bufA, UA_ByteString *const bufB) {
+ UA_ByteString tmp = *bufA;
+ *bufA = *bufB;
+ *bufB = tmp;
+}
+
+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)
+ return UA_STATUSCODE_BADINTERNALERROR;
+
+ Basic128Rsa15_PolicyContext *pc =
+ (Basic128Rsa15_PolicyContext *)securityPolicy->policyContext;
+
+ size_t hashLen = 0;
+ const mbedtls_md_info_t *mdInfo = mbedtls_md_info_from_type(MBEDTLS_MD_SHA1);
+ hashLen = (size_t)mbedtls_md_get_size(mdInfo);
+
+ 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_ByteString ANext_and_seed;
+ UA_ByteString_allocBuffer(&ANext_and_seed, hashLen + seed->length);
+ memcpy(ANext_and_seed.data + hashLen, seed->data, seed->length);
+
+ UA_ByteString A = {
+ hashLen,
+ A_and_seed.data
+ };
+
+ UA_ByteString ANext = {
+ hashLen,
+ ANext_and_seed.data
+ };
+
+ md_hmac(&pc->sha1MdContext, secret, seed, A.data);
+
+ 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;
+ }
+
+ md_hmac(&pc->sha1MdContext, secret, &A_and_seed, outSegment.data);
+ md_hmac(&pc->sha1MdContext, secret, &A, ANext.data);
+
+ 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;
+ }
+
+ if(bufferAllocated) {
+ memcpy(out->data + offset, outSegment.data, out->length - offset);
+ UA_ByteString_deleteMembers(&outSegment);
+ }
+
+ swapBuffers(&ANext_and_seed, &A_and_seed);
+ swapBuffers(&ANext, &A);
+ }
+
+ UA_ByteString_deleteMembers(&A_and_seed);
+ UA_ByteString_deleteMembers(&ANext_and_seed);
+ return UA_STATUSCODE_GOOD;
+}
+
+static UA_StatusCode
+sym_generateNonce_sp_basic128rsa15(const UA_SecurityPolicy *securityPolicy,
+ UA_ByteString *out) {
+ if(securityPolicy == NULL || securityPolicy->policyContext == NULL || out == NULL)
+ return UA_STATUSCODE_BADINTERNALERROR;
+
+ Basic128Rsa15_PolicyContext *data =
+ (Basic128Rsa15_PolicyContext *)securityPolicy->policyContext;
+
+ int mbedErr = mbedtls_ctr_drbg_random(&data->drbgContext, out->data, out->length);
+ UA_MBEDTLS_ERRORHANDLING_RETURN(UA_STATUSCODE_BADUNEXPECTEDERROR);
+
+ return UA_STATUSCODE_GOOD;
+}
+
+/*****************/
+/* ChannelModule */
+/*****************/
+
+/* Assumes that the certificate has been verified externally */
+static UA_StatusCode
+parseRemoteCertificate_sp_basic128rsa15(Basic128Rsa15_ChannelContext *cc,
+ const UA_ByteString *remoteCertificate) {
+ if(remoteCertificate == NULL || cc == NULL)
+ return UA_STATUSCODE_BADINTERNALERROR;
+
+ const UA_SecurityPolicy *securityPolicy = cc->policyContext->securityPolicy;
+
+ /* Parse the certificate */
+ int mbedErr = mbedtls_x509_crt_parse(&cc->remoteCertificate, remoteCertificate->data,
+ remoteCertificate->length);
+ UA_MBEDTLS_ERRORHANDLING_RETURN(UA_STATUSCODE_BADSECURITYCHECKSFAILED);
+
+ /* Check the key length */
+ 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;
+
+ 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);
+
+ mbedtls_x509_crt_free(&cc->remoteCertificate);
+
+ UA_free(cc);
+}
+
+static UA_StatusCode
+channelContext_newContext_sp_basic128rsa15(const UA_SecurityPolicy *securityPolicy,
+ const UA_ByteString *remoteCertificate,
+ void **pp_contextData) {
+ if(securityPolicy == NULL || remoteCertificate == NULL || pp_contextData == NULL)
+ return UA_STATUSCODE_BADINTERNALERROR;
+
+ /* Allocate the channel context */
+ *pp_contextData = UA_malloc(sizeof(Basic128Rsa15_ChannelContext));
+ if(*pp_contextData == NULL)
+ return UA_STATUSCODE_BADOUTOFMEMORY;
+
+ Basic128Rsa15_ChannelContext *cc = (Basic128Rsa15_ChannelContext *)*pp_contextData;
+
+ /* Initialize the channel context */
+ cc->policyContext = (Basic128Rsa15_PolicyContext *)securityPolicy->policyContext;
+
+ UA_ByteString_init(&cc->localSymSigningKey);
+ UA_ByteString_init(&cc->localSymEncryptingKey);
+ UA_ByteString_init(&cc->localSymIv);
+
+ UA_ByteString_init(&cc->remoteSymSigningKey);
+ UA_ByteString_init(&cc->remoteSymEncryptingKey);
+ UA_ByteString_init(&cc->remoteSymIv);
+
+ mbedtls_x509_crt_init(&cc->remoteCertificate);
+
+ // TODO: this can be optimized so that we dont allocate memory before parsing the certificate
+ UA_StatusCode retval = parseRemoteCertificate_sp_basic128rsa15(cc, remoteCertificate);
+ if(retval != UA_STATUSCODE_GOOD) {
+ channelContext_deleteContext_sp_basic128rsa15(cc);
+ *pp_contextData = NULL;
+ }
+ return retval;
+}
+
+static UA_StatusCode
+channelContext_setLocalSymEncryptingKey_sp_basic128rsa15(Basic128Rsa15_ChannelContext *cc,
+ const UA_ByteString *key) {
+ if(key == NULL || cc == NULL)
+ return UA_STATUSCODE_BADINTERNALERROR;
+
+ UA_ByteString_deleteMembers(&cc->localSymEncryptingKey);
+ return UA_ByteString_copy(key, &cc->localSymEncryptingKey);
+}
+
+static UA_StatusCode
+channelContext_setLocalSymSigningKey_sp_basic128rsa15(Basic128Rsa15_ChannelContext *cc,
+ const UA_ByteString *key) {
+ if(key == NULL || cc == NULL)
+ return UA_STATUSCODE_BADINTERNALERROR;
+
+ UA_ByteString_deleteMembers(&cc->localSymSigningKey);
+ return UA_ByteString_copy(key, &cc->localSymSigningKey);
+}
+
+
+static UA_StatusCode
+channelContext_setLocalSymIv_sp_basic128rsa15(Basic128Rsa15_ChannelContext *cc,
+ const UA_ByteString *iv) {
+ if(iv == NULL || cc == NULL)
+ return UA_STATUSCODE_BADINTERNALERROR;
+
+ UA_ByteString_deleteMembers(&cc->localSymIv);
+ return UA_ByteString_copy(iv, &cc->localSymIv);
+}
+
+static UA_StatusCode
+channelContext_setRemoteSymEncryptingKey_sp_basic128rsa15(Basic128Rsa15_ChannelContext *cc,
+ const UA_ByteString *key) {
+ if(key == NULL || cc == NULL)
+ return UA_STATUSCODE_BADINTERNALERROR;
+
+ UA_ByteString_deleteMembers(&cc->remoteSymEncryptingKey);
+ return UA_ByteString_copy(key, &cc->remoteSymEncryptingKey);
+}
+
+static UA_StatusCode
+channelContext_setRemoteSymSigningKey_sp_basic128rsa15(Basic128Rsa15_ChannelContext *cc,
+ const UA_ByteString *key) {
+ if(key == NULL || cc == NULL)
+ return UA_STATUSCODE_BADINTERNALERROR;
+
+ UA_ByteString_deleteMembers(&cc->remoteSymSigningKey);
+ return UA_ByteString_copy(key, &cc->remoteSymSigningKey);
+}
+
+static UA_StatusCode
+channelContext_setRemoteSymIv_sp_basic128rsa15(Basic128Rsa15_ChannelContext *cc,
+ const UA_ByteString *iv) {
+ if(iv == NULL || cc == NULL)
+ return UA_STATUSCODE_BADINTERNALERROR;
+
+ UA_ByteString_deleteMembers(&cc->remoteSymIv);
+ return UA_ByteString_copy(iv, &cc->remoteSymIv);
+}
+
+static UA_StatusCode
+channelContext_compareCertificate_sp_basic128rsa15(const Basic128Rsa15_ChannelContext *cc,
+ const UA_ByteString *certificate) {
+ if(cc == NULL || certificate == NULL)
+ return UA_STATUSCODE_BADINTERNALERROR;
+
+ const UA_SecurityPolicy *securityPolicy = cc->policyContext->securityPolicy;
+
+ mbedtls_x509_crt cert;
+ mbedtls_x509_crt_init(&cert);
+ int mbedErr = mbedtls_x509_crt_parse(&cert, certificate->data, certificate->length);
+ if(mbedErr) {
+ UA_LOG_MBEDERR;
+ return UA_STATUSCODE_BADSECURITYCHECKSFAILED;
+ }
+
+ 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;
+
+ mbedtls_x509_crt_free(&cert);
+ return retval;
+}
+
+static void
+deleteMembers_sp_basic128rsa15(UA_SecurityPolicy *securityPolicy) {
+ if(securityPolicy == NULL)
+ return;
+
+ if(securityPolicy->policyContext == NULL)
+ return;
+
+ UA_ByteString_deleteMembers(&securityPolicy->localCertificate);
+
+ /* delete all allocated members in the context */
+ Basic128Rsa15_PolicyContext *pc = (Basic128Rsa15_PolicyContext *)
+ securityPolicy->policyContext;
+
+ mbedtls_ctr_drbg_free(&pc->drbgContext);
+ mbedtls_entropy_free(&pc->entropyContext);
+ mbedtls_pk_free(&pc->localPrivateKey);
+ mbedtls_md_free(&pc->sha1MdContext);
+ UA_ByteString_deleteMembers(&pc->localCertThumbprint);
+
+ UA_LOG_DEBUG(securityPolicy->logger, UA_LOGCATEGORY_SECURITYPOLICY,
+ "Deleted members of EndpointContext for sp_basic128rsa15");
+
+ UA_free(pc);
+ securityPolicy->policyContext = NULL;
+}
+
+static UA_StatusCode
+policyContext_newContext_sp_basic128rsa15(UA_SecurityPolicy *securityPolicy,
+ const UA_ByteString localPrivateKey) {
+ UA_StatusCode retval = UA_STATUSCODE_GOOD;
+ if(securityPolicy == NULL)
+ return UA_STATUSCODE_BADINTERNALERROR;
+
+ Basic128Rsa15_PolicyContext *pc = (Basic128Rsa15_PolicyContext *)
+ UA_malloc(sizeof(Basic128Rsa15_PolicyContext));
+ securityPolicy->policyContext = (void *)pc;
+ if(!pc) {
+ retval = UA_STATUSCODE_BADOUTOFMEMORY;
+ goto error;
+ }
+
+ /* Initialize the PolicyContext */
+ memset(pc, 0, sizeof(Basic128Rsa15_PolicyContext));
+ mbedtls_ctr_drbg_init(&pc->drbgContext);
+ mbedtls_entropy_init(&pc->entropyContext);
+ mbedtls_pk_init(&pc->localPrivateKey);
+ mbedtls_md_init(&pc->sha1MdContext);
+ pc->securityPolicy = securityPolicy;
+
+ /* Initialized the message digest */
+ const mbedtls_md_info_t *const mdInfo = mbedtls_md_info_from_type(MBEDTLS_MD_SHA1);
+ int mbedErr = mbedtls_md_setup(&pc->sha1MdContext, mdInfo, MBEDTLS_MD_SHA1);
+ UA_MBEDTLS_ERRORHANDLING(UA_STATUSCODE_BADOUTOFMEMORY);
+ if(retval != UA_STATUSCODE_GOOD)
+ goto error;
+
+ /* Add the system entropy source */
+ mbedErr = mbedtls_entropy_add_source(&pc->entropyContext,
+ mbedtls_platform_entropy_poll, NULL, 0,
+ MBEDTLS_ENTROPY_SOURCE_STRONG);
+ UA_MBEDTLS_ERRORHANDLING(UA_STATUSCODE_BADSECURITYCHECKSFAILED);
+ if(retval != UA_STATUSCODE_GOOD)
+ goto error;
+
+ /* Seed the RNG */
+ char *personalization = "open62541-drbg";
+ mbedErr = mbedtls_ctr_drbg_seed(&pc->drbgContext, mbedtls_entropy_func,
+ &pc->entropyContext,
+ (const unsigned char *)personalization, 14);
+ UA_MBEDTLS_ERRORHANDLING(UA_STATUSCODE_BADSECURITYCHECKSFAILED);
+ if(retval != UA_STATUSCODE_GOOD)
+ goto error;
+
+ /* Set the private key */
+ mbedErr = mbedtls_pk_parse_key(&pc->localPrivateKey,
+ localPrivateKey.data, localPrivateKey.length,
+ NULL, 0);
+ UA_MBEDTLS_ERRORHANDLING(UA_STATUSCODE_BADSECURITYCHECKSFAILED);
+ if(retval != UA_STATUSCODE_GOOD)
+ 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_basic128rsa15(pc->securityPolicy,
+ &securityPolicy->localCertificate,
+ &pc->localCertThumbprint);
+ if(retval != UA_STATUSCODE_GOOD)
+ goto error;
+
+ return UA_STATUSCODE_GOOD;
+
+error:
+ UA_LOG_ERROR(securityPolicy->logger, UA_LOGCATEGORY_SECURITYPOLICY,
+ "Could not create securityContext");
+ if(securityPolicy->policyContext != NULL)
+ deleteMembers_sp_basic128rsa15(securityPolicy);
+ return retval;
+}
+
+UA_StatusCode
+UA_SecurityPolicy_Basic128Rsa15(UA_SecurityPolicy *policy, UA_CertificateVerification *certificateVerification,
+ const UA_ByteString localCertificate, const UA_ByteString localPrivateKey,
+ UA_Logger logger) {
+ memset(policy, 0, sizeof(UA_SecurityPolicy));
+ policy->logger = logger;
+
+ policy->policyUri = UA_STRING("http://opcfoundation.org/UA/SecurityPolicy#Basic128Rsa15");
+
+ UA_SecurityPolicyAsymmetricModule *const asymmetricModule = &policy->asymmetricModule;
+ UA_SecurityPolicySymmetricModule *const symmetricModule = &policy->symmetricModule;
+ UA_SecurityPolicyChannelModule *const channelModule = &policy->channelModule;
+
+ /* Copy the certificate and add a NULL to the end */
+ UA_StatusCode retval =
+ UA_ByteString_allocBuffer(&policy->localCertificate, localCertificate.length + 1);
+ if(retval != UA_STATUSCODE_GOOD)
+ return retval;
+ memcpy(policy->localCertificate.data, localCertificate.data, localCertificate.length);
+ policy->localCertificate.data[localCertificate.length] = '\0';
+ policy->localCertificate.length--;
+ policy->certificateVerification = certificateVerification;
+
+ /* AsymmetricModule */
+ UA_SecurityPolicySignatureAlgorithm *asym_signatureAlgorithm =
+ &asymmetricModule->cryptoModule.signatureAlgorithm;
+ 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;
+ asym_signatureAlgorithm->sign =
+ (UA_StatusCode (*)(const UA_SecurityPolicy *, void *,
+ const UA_ByteString *, UA_ByteString *))asym_sign_sp_basic128rsa15;
+ asym_signatureAlgorithm->getLocalSignatureSize =
+ (size_t (*)(const UA_SecurityPolicy *, const void *))asym_getLocalSignatureSize_sp_basic128rsa15;
+ asym_signatureAlgorithm->getRemoteSignatureSize =
+ (size_t (*)(const UA_SecurityPolicy *, const void *))asym_getRemoteSignatureSize_sp_basic128rsa15;
+ asym_signatureAlgorithm->getLocalKeyLength = NULL; // TODO: Write function
+ asym_signatureAlgorithm->getRemoteKeyLength = NULL; // TODO: Write function
+
+ UA_SecurityPolicyEncryptionAlgorithm *asym_encryptionAlgorithm =
+ &asymmetricModule->cryptoModule.encryptionAlgorithm;
+ asym_encryptionAlgorithm->uri = UA_STRING("TODO: ALG URI");
+ asym_encryptionAlgorithm->encrypt =
+ (UA_StatusCode(*)(const UA_SecurityPolicy *, void *, UA_ByteString *))asym_encrypt_sp_basic128rsa15;
+ asym_encryptionAlgorithm->decrypt =
+ (UA_StatusCode(*)(const UA_SecurityPolicy *, void *, UA_ByteString *))
+ asym_decrypt_sp_basic128rsa15;
+ asym_encryptionAlgorithm->getLocalKeyLength = NULL; // TODO: Write function
+ 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
+ asym_encryptionAlgorithm->getRemotePlainTextBlockSize =
+ (size_t (*)(const UA_SecurityPolicy *, const void *))asym_getRemotePlainTextBlockSize_sp_basic128rsa15;
+
+ asymmetricModule->makeCertificateThumbprint = asym_makeThumbprint_sp_basic128rsa15;
+ asymmetricModule->compareCertificateThumbprint =
+ asymmetricModule_compareCertificateThumbprint_sp_basic128rsa15;
+
+ /* SymmetricModule */
+ symmetricModule->generateKey = sym_generateKey_sp_basic128rsa15;
+ symmetricModule->generateNonce = sym_generateNonce_sp_basic128rsa15;
+
+ 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 (*)(const UA_SecurityPolicy *, 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;
+ 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;
+ sym_signatureAlgorithm->getRemoteKeyLength =
+ (size_t (*)(const UA_SecurityPolicy *,
+ 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;
+ sym_encryptionAlgorithm->decrypt =
+ (UA_StatusCode(*)(const UA_SecurityPolicy *, 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;
+ sym_encryptionAlgorithm->getRemotePlainTextBlockSize =
+ (size_t (*)(const UA_SecurityPolicy *, const void *))sym_getPlainTextBlockSize_sp_basic128rsa15;
+ symmetricModule->secureChannelNonceLength = 16;
+
+ // Use the same signature algorithm as the asymmetric component for certificate signing (see standard)
+ policy->certificateSigningAlgorithm = policy->asymmetricModule.cryptoModule.signatureAlgorithm;
+
+ /* ChannelModule */
+ channelModule->newContext = channelContext_newContext_sp_basic128rsa15;
+ channelModule->deleteContext = (void (*)(void *))
+ channelContext_deleteContext_sp_basic128rsa15;
+
+ channelModule->setLocalSymEncryptingKey = (UA_StatusCode (*)(void *, const UA_ByteString *))
+ channelContext_setLocalSymEncryptingKey_sp_basic128rsa15;
+ channelModule->setLocalSymSigningKey = (UA_StatusCode (*)(void *, const UA_ByteString *))
+ channelContext_setLocalSymSigningKey_sp_basic128rsa15;
+ channelModule->setLocalSymIv = (UA_StatusCode (*)(void *, const UA_ByteString *))
+ channelContext_setLocalSymIv_sp_basic128rsa15;
+
+ channelModule->setRemoteSymEncryptingKey = (UA_StatusCode (*)(void *, const UA_ByteString *))
+ channelContext_setRemoteSymEncryptingKey_sp_basic128rsa15;
+ channelModule->setRemoteSymSigningKey = (UA_StatusCode (*)(void *, const UA_ByteString *))
+ channelContext_setRemoteSymSigningKey_sp_basic128rsa15;
+ channelModule->setRemoteSymIv = (UA_StatusCode (*)(void *, const UA_ByteString *))
+ channelContext_setRemoteSymIv_sp_basic128rsa15;
+
+ channelModule->compareCertificate = (UA_StatusCode (*)(const void *, const UA_ByteString *))
+ channelContext_compareCertificate_sp_basic128rsa15;
+
+ policy->deleteMembers = deleteMembers_sp_basic128rsa15;
+
+ return policyContext_newContext_sp_basic128rsa15(policy, localPrivateKey);
+}
+
+#endif /* UA_ENABLE_ENCRYPTION */
+
+/*********************************** amalgamated original file "/home/jvoe/open62541/plugins/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
+ * 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
+ */
+
+
+#ifdef UA_ENABLE_ENCRYPTION
+
+#include <mbedtls/aes.h>
+#include <mbedtls/md.h>
+#include <mbedtls/sha256.h>
+#include <mbedtls/x509_crt.h>
+#include <mbedtls/ctr_drbg.h>
+#include <mbedtls/entropy.h>
+#include <mbedtls/entropy_poll.h>
+#include <mbedtls/error.h>
+#include <mbedtls/version.h>
+#include <mbedtls/sha1.h>
+
+
+/* Notes:
+ * mbedTLS' AES allows in-place encryption and decryption. Sow we don't have to
+ * allocate temp buffers.
+ * https://tls.mbed.org/discussions/generic/in-place-decryption-with-aes256-same-input-output-buffer
+ */
+
+#define UA_SECURITYPOLICY_BASIC256SHA256_RSAPADDING_LEN 42
+#define UA_SHA1_LENGTH 20
+#define UA_SHA256_LENGTH 32
+#define UA_BASIC256SHA256_SYM_SIGNING_KEY_LENGTH 32
+#define UA_SECURITYPOLICY_BASIC256SHA256_SYM_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
+
+#define UA_LOG_MBEDERR \
+ char errBuff[300]; \
+ mbedtls_strerror(mbedErr, errBuff, 300); \
+ UA_LOG_WARNING(securityPolicy->logger, UA_LOGCATEGORY_SECURITYPOLICY, \
+ "mbedTLS returned an error: %s", errBuff); \
+
+#define UA_MBEDTLS_ERRORHANDLING(errorcode) \
+ if(mbedErr) { \
+ UA_LOG_MBEDERR \
+ retval = errorcode; \
+ }
+
+#define UA_MBEDTLS_ERRORHANDLING_RETURN(errorcode) \
+ if(mbedErr) { \
+ UA_LOG_MBEDERR \
+ return errorcode; \
+ }
+
+typedef struct {
+ const UA_SecurityPolicy *securityPolicy;
+ UA_ByteString localCertThumbprint;
+
+ mbedtls_ctr_drbg_context drbgContext;
+ mbedtls_entropy_context entropyContext;
+ mbedtls_md_context_t sha256MdContext;
+ mbedtls_pk_context localPrivateKey;
+} Basic256Sha256_PolicyContext;
+
+typedef struct {
+ Basic256Sha256_PolicyContext *policyContext;
+
+ UA_ByteString localSymSigningKey;
+ UA_ByteString localSymEncryptingKey;
+ UA_ByteString localSymIv;
+
+ UA_ByteString remoteSymSigningKey;
+ UA_ByteString remoteSymEncryptingKey;
+ UA_ByteString remoteSymIv;
+
+ mbedtls_x509_crt remoteCertificate;
+} Basic256Sha256_ChannelContext;
+
+/********************/
+/* AsymmetricModule */
+/********************/
+
+/* VERIFY AsymmetricSignatureAlgorithm_RSA-PKCS15-SHA2-256 */
+static UA_StatusCode
+asym_verify_sp_basic256sha256(const UA_SecurityPolicy *securityPolicy,
+ Basic256Sha256_ChannelContext *cc,
+ const UA_ByteString *message,
+ const UA_ByteString *signature) {
+ if(securityPolicy == NULL || message == NULL || signature == NULL || cc == NULL)
+ return UA_STATUSCODE_BADINTERNALERROR;
+
+ unsigned char hash[UA_SHA256_LENGTH];
+#if MBEDTLS_VERSION_NUMBER >= 0x02070000
+ // TODO check return status
+ mbedtls_sha256_ret(message->data, message->length, hash, 0);
+#else
+ mbedtls_sha256(message->data, message->length, hash, 0);
+#endif
+
+ /* 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);
+
+ /* 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_MBEDTLS_ERRORHANDLING_RETURN(UA_STATUSCODE_BADSECURITYCHECKSFAILED);
+ return UA_STATUSCODE_GOOD;
+}
+
+/* AsymmetricSignatureAlgorithm_RSA-PKCS15-SHA2-256 */
+static UA_StatusCode
+asym_sign_sp_basic256sha256(const UA_SecurityPolicy *securityPolicy,
+ Basic256Sha256_ChannelContext *cc,
+ const UA_ByteString *message,
+ UA_ByteString *signature) {
+ if(securityPolicy == NULL || message == NULL || signature == NULL || cc == NULL)
+ return UA_STATUSCODE_BADINTERNALERROR;
+
+ unsigned char hash[UA_SHA256_LENGTH];
+#if MBEDTLS_VERSION_NUMBER >= 0x02070000
+ // TODO check return status
+ mbedtls_sha256_ret(message->data, message->length, hash, 0);
+#else
+ mbedtls_sha256(message->data, message->length, hash, 0);
+#endif
+
+ Basic256Sha256_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);
+
+ size_t sigLen = 0;
+
+ /* 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,
+ &sigLen, mbedtls_ctr_drbg_random,
+ &pc->drbgContext);
+ UA_MBEDTLS_ERRORHANDLING_RETURN(UA_STATUSCODE_BADINTERNALERROR);
+ return UA_STATUSCODE_GOOD;
+}
+
+static size_t
+asym_getLocalSignatureSize_sp_basic256sha256(const UA_SecurityPolicy *securityPolicy,
+ const Basic256Sha256_ChannelContext *cc) {
+ if(securityPolicy == NULL || cc == NULL)
+ return 0;
+
+ return mbedtls_pk_rsa(cc->policyContext->localPrivateKey)->len;
+}
+
+static size_t
+asym_getRemoteSignatureSize_sp_basic256sha256(const UA_SecurityPolicy *securityPolicy,
+ const Basic256Sha256_ChannelContext *cc) {
+ if(securityPolicy == NULL || cc == NULL)
+ return 0;
+
+ return mbedtls_pk_rsa(cc->remoteCertificate.pk)->len;
+}
+
+/* AsymmetricEncryptionAlgorithm_RSA-OAEP-SHA1 */
+static UA_StatusCode
+asym_encrypt_sp_basic256sha256(const UA_SecurityPolicy *securityPolicy,
+ Basic256Sha256_ChannelContext *cc,
+ UA_ByteString *data) {
+ if(securityPolicy == NULL || cc == NULL || data == NULL)
+ return UA_STATUSCODE_BADINTERNALERROR;
+
+ const size_t plainTextBlockSize = securityPolicy->asymmetricModule.cryptoModule.encryptionAlgorithm.
+ getRemotePlainTextBlockSize(securityPolicy, cc);
+
+ 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_V21, MBEDTLS_MD_SHA1);
+
+ 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(retval != UA_STATUSCODE_GOOD)
+ return retval;
+
+ size_t lenDataToEncrypt = data->length;
+ size_t inOffset = 0;
+ size_t offset = 0;
+ const unsigned char *label = NULL;
+ Basic256Sha256_PolicyContext *pc = cc->policyContext;
+ while(lenDataToEncrypt >= plainTextBlockSize) {
+ int mbedErr = mbedtls_rsa_rsaes_oaep_encrypt(remoteRsaContext, mbedtls_ctr_drbg_random,
+ &pc->drbgContext, MBEDTLS_RSA_PUBLIC,
+ label, 0, plainTextBlockSize,
+ data->data + inOffset, encrypted.data + offset);
+
+ UA_MBEDTLS_ERRORHANDLING(UA_STATUSCODE_BADINTERNALERROR);
+ if(retval != UA_STATUSCODE_GOOD) {
+ UA_ByteString_deleteMembers(&encrypted);
+ return retval;
+ }
+
+ inOffset += plainTextBlockSize;
+ offset += remoteRsaContext->len;
+ lenDataToEncrypt -= plainTextBlockSize;
+ }
+
+ memcpy(data->data, encrypted.data, offset);
+ UA_ByteString_deleteMembers(&encrypted);
+
+ return UA_STATUSCODE_GOOD;
+}
+
+/* AsymmetricEncryptionAlgorithm_RSA-OAEP-SHA1 */
+static UA_StatusCode
+asym_decrypt_sp_basic256sha256(const UA_SecurityPolicy *securityPolicy,
+ Basic256Sha256_ChannelContext *cc,
+ UA_ByteString *data) {
+ if(securityPolicy == NULL || 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_V21, MBEDTLS_MD_SHA1);
+
+ if(data->length % rsaContext->len != 0)
+ return UA_STATUSCODE_BADINTERNALERROR;
+
+ UA_ByteString decrypted;
+ UA_StatusCode retval = UA_ByteString_allocBuffer(&decrypted, data->length);
+ if(retval != UA_STATUSCODE_GOOD)
+ return retval;
+
+ size_t lenDataToDecrypt = data->length;
+ size_t inOffset = 0;
+ size_t offset = 0;
+ size_t outLength = 0;
+ const unsigned char *label = NULL;
+ Basic256Sha256_PolicyContext *pc = cc->policyContext;
+
+ while(lenDataToDecrypt >= rsaContext->len) {
+ int mbedErr = mbedtls_rsa_rsaes_oaep_decrypt(rsaContext, mbedtls_ctr_drbg_random,
+ &pc->drbgContext, MBEDTLS_RSA_PRIVATE,
+ label, 0, &outLength,
+ data->data + inOffset,
+ decrypted.data + offset,
+ decrypted.length - offset);
+ if(mbedErr)
+ UA_ByteString_deleteMembers(&decrypted); // TODO: Maybe change error macro to jump to cleanup?
+ UA_MBEDTLS_ERRORHANDLING_RETURN(UA_STATUSCODE_BADSECURITYCHECKSFAILED);
+
+ inOffset += rsaContext->len;
+ offset += outLength;
+ lenDataToDecrypt -= rsaContext->len;
+ }
+
+ if(lenDataToDecrypt == 0) {
+ memcpy(data->data, decrypted.data, offset);
+ data->length = offset;
+ } else {
+ retval = UA_STATUSCODE_BADINTERNALERROR;
+ }
+
+ UA_ByteString_deleteMembers(&decrypted);
+ return retval;
+}
+
+static size_t
+asym_getRemoteEncryptionKeyLength_sp_basic256sha256(const UA_SecurityPolicy *securityPolicy,
+ 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,
+ UA_ByteString *thumbprint) {
+ if(securityPolicy == NULL || certificate == NULL || thumbprint == NULL)
+ return UA_STATUSCODE_BADINTERNALERROR;
+
+ if(UA_ByteString_equal(certificate, &UA_BYTESTRING_NULL))
+ return UA_STATUSCODE_BADINTERNALERROR;
+
+ if(thumbprint->length != UA_SHA1_LENGTH)
+ return UA_STATUSCODE_BADINTERNALERROR;
+
+ /* 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;
+}
+
+static UA_StatusCode
+asymmetricModule_compareCertificateThumbprint_sp_basic256sha256(const UA_SecurityPolicy *securityPolicy,
+ const UA_ByteString *certificateThumbprint) {
+ if(securityPolicy == NULL || certificateThumbprint == NULL)
+ return UA_STATUSCODE_BADINTERNALERROR;
+
+ Basic256Sha256_PolicyContext *pc = (Basic256Sha256_PolicyContext *)securityPolicy->policyContext;
+ if(!UA_ByteString_equal(certificateThumbprint, &pc->localCertThumbprint))
+ return UA_STATUSCODE_BADCERTIFICATEINVALID;
+
+ return UA_STATUSCODE_GOOD;
+}
+
+/*******************/
+/* SymmetricModule */
+/*******************/
+
+static void
+md_hmac_Basic256Sha256(mbedtls_md_context_t *context, const UA_ByteString *key,
+ const UA_ByteString *in, unsigned char out[32]) {
+ 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 UA_StatusCode
+sym_verify_sp_basic256sha256(const UA_SecurityPolicy *securityPolicy,
+ Basic256Sha256_ChannelContext *cc,
+ const UA_ByteString *message,
+ const UA_ByteString *signature) {
+ if(securityPolicy == NULL || 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");
+ return UA_STATUSCODE_BADSECURITYCHECKSFAILED;
+ }
+
+ Basic256Sha256_PolicyContext *pc =
+ (Basic256Sha256_PolicyContext *)securityPolicy->policyContext;
+
+ unsigned char mac[UA_SHA256_LENGTH];
+ md_hmac_Basic256Sha256(&pc->sha256MdContext, &cc->remoteSymSigningKey, message, mac);
+
+ /* Compare with Signature */
+ if(memcmp(signature->data, mac, UA_SHA256_LENGTH) != 0)
+ return UA_STATUSCODE_BADSECURITYCHECKSFAILED;
+ return UA_STATUSCODE_GOOD;
+}
+
+static UA_StatusCode
+sym_sign_sp_basic256sha256(const UA_SecurityPolicy *securityPolicy,
+ const Basic256Sha256_ChannelContext *cc,
+ const UA_ByteString *message,
+ UA_ByteString *signature) {
+ if(signature->length != UA_SHA256_LENGTH)
+ return UA_STATUSCODE_BADINTERNALERROR;
+
+ md_hmac_Basic256Sha256(&cc->policyContext->sha256MdContext, &cc->localSymSigningKey,
+ message, signature->data);
+ return UA_STATUSCODE_GOOD;
+}
+
+static size_t
+sym_getSignatureSize_sp_basic256sha256(const UA_SecurityPolicy *securityPolicy,
+ const void *channelContext) {
+ return UA_SHA256_LENGTH;
+}
+
+static size_t
+sym_getSigningKeyLength_sp_basic256sha256(const UA_SecurityPolicy *const securityPolicy,
+ const void *const channelContext) {
+ return UA_BASIC256SHA256_SYM_SIGNING_KEY_LENGTH;
+}
+
+static size_t
+sym_getEncryptionKeyLength_sp_basic256sha256(const UA_SecurityPolicy *securityPolicy,
+ 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) {
+ return UA_SECURITYPOLICY_BASIC256SHA256_SYM_ENCRYPTION_BLOCK_SIZE;
+}
+
+static size_t
+sym_getPlainTextBlockSize_sp_basic256sha256(const UA_SecurityPolicy *const securityPolicy,
+ const void *const 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,
+ UA_ByteString *data) {
+ if(securityPolicy == NULL || cc == NULL || data == NULL)
+ return UA_STATUSCODE_BADINTERNALERROR;
+
+ if(cc->localSymIv.length !=
+ securityPolicy->symmetricModule.cryptoModule.encryptionAlgorithm.getLocalBlockSize(securityPolicy, cc))
+ 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.");
+ return UA_STATUSCODE_BADINTERNALERROR;
+ }
+
+ /* 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);
+ UA_MBEDTLS_ERRORHANDLING_RETURN(UA_STATUSCODE_BADINTERNALERROR);
+
+ 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);
+ UA_MBEDTLS_ERRORHANDLING(UA_STATUSCODE_BADINTERNALERROR);
+ UA_ByteString_deleteMembers(&ivCopy);
+ return retval;
+}
+
+static UA_StatusCode
+sym_decrypt_sp_basic256sha256(const UA_SecurityPolicy *securityPolicy,
+ const Basic256Sha256_ChannelContext *cc,
+ UA_ByteString *data) {
+ if(securityPolicy == NULL || cc == NULL || data == NULL)
+ return UA_STATUSCODE_BADINTERNALERROR;
+
+ size_t encryptionBlockSize =
+ securityPolicy->symmetricModule.cryptoModule.encryptionAlgorithm.getLocalBlockSize(securityPolicy, cc);
+
+ 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.");
+ 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);
+ UA_MBEDTLS_ERRORHANDLING_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);
+ UA_MBEDTLS_ERRORHANDLING(UA_STATUSCODE_BADINTERNALERROR);
+ UA_ByteString_deleteMembers(&ivCopy);
+ return retval;
+}
+
+static void
+swapBuffers_Basic256Sha256(UA_ByteString *const bufA, UA_ByteString *const bufB) {
+ UA_ByteString tmp = *bufA;
+ *bufA = *bufB;
+ *bufB = tmp;
+}
+
+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)
+ return UA_STATUSCODE_BADINTERNALERROR;
+
+ Basic256Sha256_PolicyContext *pc =
+ (Basic256Sha256_PolicyContext *)securityPolicy->policyContext;
+
+ size_t hashLen = 0;
+ const mbedtls_md_info_t *mdInfo = mbedtls_md_info_from_type(MBEDTLS_MD_SHA256);
+ hashLen = (size_t)mbedtls_md_get_size(mdInfo);
+
+ 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_ByteString ANext_and_seed;
+ UA_ByteString_allocBuffer(&ANext_and_seed, hashLen + seed->length);
+ memcpy(ANext_and_seed.data + hashLen, seed->data, seed->length);
+
+ UA_ByteString A = {
+ hashLen,
+ A_and_seed.data
+ };
+
+ UA_ByteString ANext = {
+ hashLen,
+ ANext_and_seed.data
+ };
+
+ md_hmac_Basic256Sha256(&pc->sha256MdContext, secret, seed, A.data);
+
+ 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;
+ }
+
+ md_hmac_Basic256Sha256(&pc->sha256MdContext, secret, &A_and_seed, outSegment.data);
+ md_hmac_Basic256Sha256(&pc->sha256MdContext, secret, &A, ANext.data);
+
+ 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;
+ }
+
+ if(bufferAllocated) {
+ memcpy(out->data + offset, outSegment.data, out->length - offset);
+ UA_ByteString_deleteMembers(&outSegment);
+ }
+
+ swapBuffers_Basic256Sha256(&ANext_and_seed, &A_and_seed);
+ swapBuffers_Basic256Sha256(&ANext, &A);
+ }
+
+ UA_ByteString_deleteMembers(&A_and_seed);
+ UA_ByteString_deleteMembers(&ANext_and_seed);
+ return UA_STATUSCODE_GOOD;
+}
+
+static UA_StatusCode
+sym_generateNonce_sp_basic256sha256(const UA_SecurityPolicy *securityPolicy,
+ UA_ByteString *out) {
+ if(securityPolicy == NULL || securityPolicy->policyContext == NULL || out == NULL)
+ return UA_STATUSCODE_BADINTERNALERROR;
+
+ Basic256Sha256_PolicyContext *data =
+ (Basic256Sha256_PolicyContext *)securityPolicy->policyContext;
+
+ int mbedErr = mbedtls_ctr_drbg_random(&data->drbgContext, out->data, out->length);
+ UA_MBEDTLS_ERRORHANDLING_RETURN(UA_STATUSCODE_BADUNEXPECTEDERROR);
+
+ return UA_STATUSCODE_GOOD;
+}
+
+/*****************/
+/* ChannelModule */
+/*****************/
+
+/* Assumes that the certificate has been verified externally */
+static UA_StatusCode
+parseRemoteCertificate_sp_basic256sha256(Basic256Sha256_ChannelContext *cc,
+ const UA_ByteString *remoteCertificate) {
+ if(remoteCertificate == NULL || cc == NULL)
+ return UA_STATUSCODE_BADINTERNALERROR;
+
+ const UA_SecurityPolicy *securityPolicy = cc->policyContext->securityPolicy;
+
+ /* Parse the certificate */
+ int mbedErr = mbedtls_x509_crt_parse(&cc->remoteCertificate, remoteCertificate->data,
+ remoteCertificate->length);
+ UA_MBEDTLS_ERRORHANDLING_RETURN(UA_STATUSCODE_BADSECURITYCHECKSFAILED);
+
+ /* Check the key length */
+ mbedtls_rsa_context *rsaContext = mbedtls_pk_rsa(cc->remoteCertificate.pk);
+ if(rsaContext->len < UA_SECURITYPOLICY_BASIC256SHA256_MINASYMKEYLENGTH ||
+ rsaContext->len > UA_SECURITYPOLICY_BASIC256SHA256_MAXASYMKEYLENGTH)
+ return UA_STATUSCODE_BADCERTIFICATEUSENOTALLOWED;
+
+ return UA_STATUSCODE_GOOD;
+}
+
+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_deleteMembers(&cc->remoteSymSigningKey);
+ UA_ByteString_deleteMembers(&cc->remoteSymEncryptingKey);
+ UA_ByteString_deleteMembers(&cc->remoteSymIv);
+
+ mbedtls_x509_crt_free(&cc->remoteCertificate);
+
+ UA_free(cc);
+}
+
+static UA_StatusCode
+channelContext_newContext_sp_basic256sha256(const UA_SecurityPolicy *securityPolicy,
+ const UA_ByteString *remoteCertificate,
+ void **pp_contextData) {
+ if(securityPolicy == NULL || remoteCertificate == NULL || pp_contextData == NULL)
+ return UA_STATUSCODE_BADINTERNALERROR;
+
+ /* Allocate the channel context */
+ *pp_contextData = UA_malloc(sizeof(Basic256Sha256_ChannelContext));
+ if(*pp_contextData == NULL)
+ return UA_STATUSCODE_BADOUTOFMEMORY;
+
+ Basic256Sha256_ChannelContext *cc = (Basic256Sha256_ChannelContext *)*pp_contextData;
+
+ /* Initialize the channel context */
+ cc->policyContext = (Basic256Sha256_PolicyContext *)securityPolicy->policyContext;
+
+ UA_ByteString_init(&cc->localSymSigningKey);
+ UA_ByteString_init(&cc->localSymEncryptingKey);
+ UA_ByteString_init(&cc->localSymIv);
+
+ UA_ByteString_init(&cc->remoteSymSigningKey);
+ UA_ByteString_init(&cc->remoteSymEncryptingKey);
+ UA_ByteString_init(&cc->remoteSymIv);
+
+ mbedtls_x509_crt_init(&cc->remoteCertificate);
+
+ // TODO: this can be optimized so that we dont allocate memory before parsing the certificate
+ UA_StatusCode retval = parseRemoteCertificate_sp_basic256sha256(cc, remoteCertificate);
+ if(retval != UA_STATUSCODE_GOOD) {
+ channelContext_deleteContext_sp_basic256sha256(cc);
+ *pp_contextData = NULL;
+ }
+ return retval;
+}
+
+static UA_StatusCode
+channelContext_setLocalSymEncryptingKey_sp_basic256sha256(Basic256Sha256_ChannelContext *cc,
+ const UA_ByteString *key) {
+ if(key == NULL || cc == NULL)
+ return UA_STATUSCODE_BADINTERNALERROR;
+
+ UA_ByteString_deleteMembers(&cc->localSymEncryptingKey);
+ return UA_ByteString_copy(key, &cc->localSymEncryptingKey);
+}
+
+static UA_StatusCode
+channelContext_setLocalSymSigningKey_sp_basic256sha256(Basic256Sha256_ChannelContext *cc,
+ const UA_ByteString *key) {
+ if(key == NULL || cc == NULL)
+ return UA_STATUSCODE_BADINTERNALERROR;
+
+ UA_ByteString_deleteMembers(&cc->localSymSigningKey);
+ return UA_ByteString_copy(key, &cc->localSymSigningKey);
+}
+
+
+static UA_StatusCode
+channelContext_setLocalSymIv_sp_basic256sha256(Basic256Sha256_ChannelContext *cc,
+ const UA_ByteString *iv) {
+ if(iv == NULL || cc == NULL)
+ return UA_STATUSCODE_BADINTERNALERROR;
+
+ UA_ByteString_deleteMembers(&cc->localSymIv);
+ return UA_ByteString_copy(iv, &cc->localSymIv);
+}
+
+static UA_StatusCode
+channelContext_setRemoteSymEncryptingKey_sp_basic256sha256(Basic256Sha256_ChannelContext *cc,
+ const UA_ByteString *key) {
+ if(key == NULL || cc == NULL)
+ return UA_STATUSCODE_BADINTERNALERROR;
+
+ UA_ByteString_deleteMembers(&cc->remoteSymEncryptingKey);
+ return UA_ByteString_copy(key, &cc->remoteSymEncryptingKey);
+}
+
+static UA_StatusCode
+channelContext_setRemoteSymSigningKey_sp_basic256sha256(Basic256Sha256_ChannelContext *cc,
+ const UA_ByteString *key) {
+ if(key == NULL || cc == NULL)
+ return UA_STATUSCODE_BADINTERNALERROR;
+
+ UA_ByteString_deleteMembers(&cc->remoteSymSigningKey);
+ return UA_ByteString_copy(key, &cc->remoteSymSigningKey);
+}
+
+static UA_StatusCode
+channelContext_setRemoteSymIv_sp_basic256sha256(Basic256Sha256_ChannelContext *cc,
+ const UA_ByteString *iv) {
+ if(iv == NULL || cc == NULL)
+ return UA_STATUSCODE_BADINTERNALERROR;
+
+ UA_ByteString_deleteMembers(&cc->remoteSymIv);
+ return UA_ByteString_copy(iv, &cc->remoteSymIv);
+}
+
+static UA_StatusCode
+channelContext_compareCertificate_sp_basic256sha256(const Basic256Sha256_ChannelContext *cc,
+ const UA_ByteString *certificate) {
+ if(cc == NULL || certificate == NULL)
+ return UA_STATUSCODE_BADINTERNALERROR;
+
+ const UA_SecurityPolicy *securityPolicy = cc->policyContext->securityPolicy;
+
+ mbedtls_x509_crt cert;
+ mbedtls_x509_crt_init(&cert);
+ int mbedErr = mbedtls_x509_crt_parse(&cert, certificate->data, certificate->length);
+ if(mbedErr) {
+ UA_LOG_MBEDERR;
+ return UA_STATUSCODE_BADSECURITYCHECKSFAILED;
+ }
+
+ 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;
+
+ mbedtls_x509_crt_free(&cert);
+ return retval;
+}
+
+static void
+deleteMembers_sp_basic256sha256(UA_SecurityPolicy *securityPolicy) {
+ if(securityPolicy == NULL)
+ return;
+
+ if(securityPolicy->policyContext == NULL)
+ return;
+
+ UA_ByteString_deleteMembers(&securityPolicy->localCertificate);
+
+ /* delete all allocated members in the context */
+ Basic256Sha256_PolicyContext *pc = (Basic256Sha256_PolicyContext *)
+ securityPolicy->policyContext;
+
+ mbedtls_ctr_drbg_free(&pc->drbgContext);
+ mbedtls_entropy_free(&pc->entropyContext);
+ mbedtls_pk_free(&pc->localPrivateKey);
+ mbedtls_md_free(&pc->sha256MdContext);
+ UA_ByteString_deleteMembers(&pc->localCertThumbprint);
+
+ UA_LOG_DEBUG(securityPolicy->logger, UA_LOGCATEGORY_SECURITYPOLICY,
+ "Deleted members of EndpointContext for sp_basic256sha256");
+
+ UA_free(pc);
+ securityPolicy->policyContext = NULL;
+}
+
+static UA_StatusCode
+policyContext_newContext_sp_basic256sha256(UA_SecurityPolicy *securityPolicy,
+ const UA_ByteString localPrivateKey) {
+ UA_StatusCode retval = UA_STATUSCODE_GOOD;
+ if(securityPolicy == NULL)
+ return UA_STATUSCODE_BADINTERNALERROR;
+
+ Basic256Sha256_PolicyContext *pc = (Basic256Sha256_PolicyContext *)
+ UA_malloc(sizeof(Basic256Sha256_PolicyContext));
+ securityPolicy->policyContext = (void *)pc;
+ if(!pc) {
+ retval = UA_STATUSCODE_BADOUTOFMEMORY;
+ goto error;
+ }
+
+ /* Initialize the PolicyContext */
+ memset(pc, 0, sizeof(Basic256Sha256_PolicyContext));
+ mbedtls_ctr_drbg_init(&pc->drbgContext);
+ mbedtls_entropy_init(&pc->entropyContext);
+ mbedtls_pk_init(&pc->localPrivateKey);
+ mbedtls_md_init(&pc->sha256MdContext);
+ pc->securityPolicy = securityPolicy;
+
+ /* 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);
+ UA_MBEDTLS_ERRORHANDLING(UA_STATUSCODE_BADOUTOFMEMORY);
+ if(retval != UA_STATUSCODE_GOOD)
+ goto error;
+
+ /* Add the system entropy source */
+ mbedErr = mbedtls_entropy_add_source(&pc->entropyContext,
+ mbedtls_platform_entropy_poll, NULL, 0,
+ MBEDTLS_ENTROPY_SOURCE_STRONG);
+ UA_MBEDTLS_ERRORHANDLING(UA_STATUSCODE_BADSECURITYCHECKSFAILED);
+ if(retval != UA_STATUSCODE_GOOD)
+ goto error;
+
+ /* Seed the RNG */
+ char *personalization = "open62541-drbg";
+ mbedErr = mbedtls_ctr_drbg_seed(&pc->drbgContext, mbedtls_entropy_func,
+ &pc->entropyContext,
+ (const unsigned char *)personalization, 14);
+ UA_MBEDTLS_ERRORHANDLING(UA_STATUSCODE_BADSECURITYCHECKSFAILED);
+ if(retval != UA_STATUSCODE_GOOD)
+ goto error;
+
+ /* Set the private key */
+ mbedErr = mbedtls_pk_parse_key(&pc->localPrivateKey,
+ localPrivateKey.data, localPrivateKey.length,
+ NULL, 0);
+ UA_MBEDTLS_ERRORHANDLING(UA_STATUSCODE_BADSECURITYCHECKSFAILED);
+ if(retval != UA_STATUSCODE_GOOD)
+ 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_basic256sha256(pc->securityPolicy,
+ &securityPolicy->localCertificate,
+ &pc->localCertThumbprint);
+ if(retval != UA_STATUSCODE_GOOD)
+ goto error;
+
+ return UA_STATUSCODE_GOOD;
+
+error:
+ UA_LOG_ERROR(securityPolicy->logger, UA_LOGCATEGORY_SECURITYPOLICY,
+ "Could not create securityContext");
+ if(securityPolicy->policyContext != NULL)
+ deleteMembers_sp_basic256sha256(securityPolicy);
+ return retval;
+}
+
+UA_StatusCode
+UA_SecurityPolicy_Basic256Sha256(UA_SecurityPolicy *policy, UA_CertificateVerification *certificateVerification,
+ const UA_ByteString localCertificate, const UA_ByteString localPrivateKey,
+ UA_Logger logger) {
+ memset(policy, 0, sizeof(UA_SecurityPolicy));
+ policy->logger = logger;
+
+ policy->policyUri = UA_STRING("http://opcfoundation.org/UA/SecurityPolicy#Basic256Sha256");
+
+ UA_SecurityPolicyAsymmetricModule *const asymmetricModule = &policy->asymmetricModule;
+ UA_SecurityPolicySymmetricModule *const symmetricModule = &policy->symmetricModule;
+ UA_SecurityPolicyChannelModule *const channelModule = &policy->channelModule;
+
+ /* Copy the certificate and add a NULL to the end */
+ UA_StatusCode retval =
+ UA_ByteString_allocBuffer(&policy->localCertificate, localCertificate.length + 1);
+ if(retval != UA_STATUSCODE_GOOD)
+ return retval;
+ memcpy(policy->localCertificate.data, localCertificate.data, localCertificate.length);
+ policy->localCertificate.data[localCertificate.length] = '\0';
+ policy->localCertificate.length--;
+ policy->certificateVerification = certificateVerification;
+
+ /* 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 (*)(const UA_SecurityPolicy *, 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;
+ asym_signatureAlgorithm->getLocalSignatureSize =
+ (size_t (*)(const UA_SecurityPolicy *, const void *))asym_getLocalSignatureSize_sp_basic256sha256;
+ asym_signatureAlgorithm->getRemoteSignatureSize =
+ (size_t (*)(const UA_SecurityPolicy *, const void *))asym_getRemoteSignatureSize_sp_basic256sha256;
+ asym_signatureAlgorithm->getLocalKeyLength = NULL; // TODO: Write function
+ asym_signatureAlgorithm->getRemoteKeyLength = NULL; // TODO: Write function
+
+ 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(*)(const UA_SecurityPolicy *, void *, UA_ByteString *))asym_encrypt_sp_basic256sha256;
+ asym_encryptionAlgorithm->decrypt =
+ (UA_StatusCode(*)(const UA_SecurityPolicy *, void *, UA_ByteString *))
+ asym_decrypt_sp_basic256sha256;
+ asym_encryptionAlgorithm->getLocalKeyLength = NULL; // TODO: Write function
+ 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
+ asym_encryptionAlgorithm->getRemotePlainTextBlockSize =
+ (size_t (*)(const UA_SecurityPolicy *, const void *))asym_getRemotePlainTextBlockSize_sp_basic256sha256;
+
+ asymmetricModule->makeCertificateThumbprint = asym_makeThumbprint_sp_basic256sha256;
+ asymmetricModule->compareCertificateThumbprint =
+ asymmetricModule_compareCertificateThumbprint_sp_basic256sha256;
+
+ /* SymmetricModule */
+ symmetricModule->generateKey = sym_generateKey_sp_basic256sha256;
+ symmetricModule->generateNonce = sym_generateNonce_sp_basic256sha256;
+
+ 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 (*)(const UA_SecurityPolicy *, 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;
+ 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;
+ sym_signatureAlgorithm->getRemoteKeyLength =
+ (size_t (*)(const UA_SecurityPolicy *,
+ 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->encrypt =
+ (UA_StatusCode(*)(const UA_SecurityPolicy *, void *, UA_ByteString *))sym_encrypt_sp_basic256sha256;
+ sym_encryptionAlgorithm->decrypt =
+ (UA_StatusCode(*)(const UA_SecurityPolicy *, 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;
+ sym_encryptionAlgorithm->getRemotePlainTextBlockSize =
+ (size_t (*)(const UA_SecurityPolicy *, const void *))sym_getPlainTextBlockSize_sp_basic256sha256;
+ symmetricModule->secureChannelNonceLength = 32;
+
+ // Use the same signature algorithm as the asymmetric component for certificate signing (see standard)
+ policy->certificateSigningAlgorithm = policy->asymmetricModule.cryptoModule.signatureAlgorithm;
+
+ /* ChannelModule */
+ channelModule->newContext = channelContext_newContext_sp_basic256sha256;
+ channelModule->deleteContext = (void (*)(void *))
+ channelContext_deleteContext_sp_basic256sha256;
+
+ channelModule->setLocalSymEncryptingKey = (UA_StatusCode (*)(void *, const UA_ByteString *))
+ channelContext_setLocalSymEncryptingKey_sp_basic256sha256;
+ channelModule->setLocalSymSigningKey = (UA_StatusCode (*)(void *, const UA_ByteString *))
+ channelContext_setLocalSymSigningKey_sp_basic256sha256;
+ channelModule->setLocalSymIv = (UA_StatusCode (*)(void *, const UA_ByteString *))
+ channelContext_setLocalSymIv_sp_basic256sha256;
+
+ channelModule->setRemoteSymEncryptingKey = (UA_StatusCode (*)(void *, const UA_ByteString *))
+ channelContext_setRemoteSymEncryptingKey_sp_basic256sha256;
+ channelModule->setRemoteSymSigningKey = (UA_StatusCode (*)(void *, const UA_ByteString *))
+ channelContext_setRemoteSymSigningKey_sp_basic256sha256;
+ channelModule->setRemoteSymIv = (UA_StatusCode (*)(void *, const UA_ByteString *))
+ channelContext_setRemoteSymIv_sp_basic256sha256;
+
+ channelModule->compareCertificate = (UA_StatusCode (*)(const void *, const UA_ByteString *))
+ channelContext_compareCertificate_sp_basic256sha256;
+
+ policy->deleteMembers = deleteMembers_sp_basic256sha256;
+
+ return policyContext_newContext_sp_basic256sha256(policy, localPrivateKey);
+}
+
+#endif /* UA_ENABLE_ENCRYPTION */