Wolfgang Hottgenroth da498bb161 * add include files and static library due to problems with AMALGAM'ED
distri and nodeset feature
* add UaModeler project including XML export
* add nodeset using test server
2016-06-08 11:21:06 +02:00

22335 lines
887 KiB
C

/* THIS IS A SINGLE-FILE DISTRIBUTION CONCATENATED FROM THE OPEN62541 SOURCES
* visit http://open62541.org/ for information about this software
* Git-Revision: unknown--git-commit-id-unknown
*/
/*
* Copyright (C) 2015 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 GNU Lesser General
* Public License, version 3 (as published by the Free Software Foundation) with
* a static linking exception 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. See the GNU Lesser General Public License for more
* details.
*/
#ifndef UA_DYNAMIC_LINKING
# define UA_DYNAMIC_LINKING
#endif
#ifndef UA_INTERNAL
#define UA_INTERNAL
#endif
#include "open62541.h"
/*********************************** amalgamated original file "/home/wn/Sources/open62541-open62541-395ce48/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
*/
#ifndef _SYS_QUEUE_H_
#define _SYS_QUEUE_H_
/*
* 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 }
#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)
#endif /* !_SYS_QUEUE_H_ */
/*********************************** amalgamated original file "/home/wn/Sources/open62541-open62541-395ce48/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
*/
/*
* This code is derived from the full C implementation, which is in turn
* derived from the canonical C++ PCG implementation. The C++ version
* has many additional features and is preferable if you can use C++ in
* your project.
*/
#include <inttypes.h>
#if __cplusplus
extern "C" {
#endif
struct pcg_state_setseq_64 { // Internals are *Private*.
uint64_t state; // RNG state. All values are possible.
uint64_t inc; // Controls which RNG sequence (stream) is
// selected. Must *always* be odd.
};
typedef struct pcg_state_setseq_64 pcg32_random_t;
// If you *must* statically initialize it, here's one.
#define PCG32_INITIALIZER { 0x853c49e6748fea9bULL, 0xda3e39cb94b95bdbULL }
// pcg32_srandom(initial_state, initseq)
// pcg32_srandom_r(rng, initial_state, initseq):
// Seed the rng. Specified in two parts, state initializer and a
// sequence selection constant (a.k.a. stream id)
void pcg32_srandom(uint64_t initial_state, uint64_t initseq);
void pcg32_srandom_r(pcg32_random_t* rng, uint64_t initial_state,
uint64_t initseq);
// pcg32_random()
// pcg32_random_r(rng)
// Generate a uniformly distributed 32-bit random number
uint32_t pcg32_random(void);
uint32_t pcg32_random_r(pcg32_random_t* rng);
// pcg32_boundedrand(bound):
// pcg32_boundedrand_r(rng, bound):
// Generate a uniformly distributed number, r, where 0 <= r < bound
uint32_t pcg32_boundedrand(uint32_t bound);
uint32_t pcg32_boundedrand_r(pcg32_random_t* rng, uint32_t bound);
#if __cplusplus
}
#endif
/*********************************** amalgamated original file "/home/wn/Sources/open62541-open62541-395ce48/deps/libc_time.h" ***********************************/
#include <limits.h>
#include <time.h>
int __secs_to_tm(long long t, struct tm *tm);
/*********************************** amalgamated original file "/home/wn/Sources/open62541-open62541-395ce48/src/ua_util.h" ***********************************/
#include <assert.h>
#define UA_assert(ignore) assert(ignore)
/*********************/
/* Memory Management */
/*********************/
/* Replace the macros with functions for custom allocators if necessary */
#include <stdlib.h> // malloc, free
#ifdef _WIN32
# include <malloc.h>
#endif
#ifndef UA_free
# define UA_free(ptr) free(ptr)
#endif
#ifndef UA_malloc
# define UA_malloc(size) malloc(size)
#endif
#ifndef UA_calloc
# define UA_calloc(num, size) calloc(num, size)
#endif
#ifndef UA_realloc
# define UA_realloc(ptr, size) realloc(ptr, size)
#endif
#ifndef NO_ALLOCA
# ifdef __GNUC__
# define UA_alloca(size) __builtin_alloca (size)
# elif defined(_WIN32)
# define UA_alloca(SIZE) _alloca(SIZE)
# else
# include <alloca.h>
# define UA_alloca(SIZE) alloca(SIZE)
# endif
#endif
#define container_of(ptr, type, member) \
(type *)((uintptr_t)ptr - offsetof(type,member))
/************************/
/* Thread Local Storage */
/************************/
#ifdef UA_ENABLE_MULTITHREADING
# ifdef __GNUC__
# define UA_THREAD_LOCAL __thread
# elif defined(_MSC_VER)
# define UA_THREAD_LOCAL __declspec(thread)
# else
# error No thread local storage keyword defined for this compiler
# endif
#else
# define UA_THREAD_LOCAL
#endif
/********************/
/* System Libraries */
/********************/
#ifdef _WIN32
# include <winsock2.h> //needed for amalgamation
# include <windows.h>
# undef SLIST_ENTRY
#endif
#include <time.h>
#if defined(_WIN32) && !defined(__MINGW32__)
int gettimeofday(struct timeval *tp, struct timezone *tzp);
#else
# include <sys/time.h>
#endif
#if defined(__APPLE__) || defined(__MACH__)
#include <mach/clock.h>
#include <mach/mach.h>
#endif
/*************************/
/* External Dependencies */
/*************************/
#ifdef UA_ENABLE_MULTITHREADING
# define _LGPL_SOURCE
# include <urcu.h>
# include <urcu/wfcqueue.h>
# include <urcu/uatomic.h>
# include <urcu/rculfhash.h>
# include <urcu/lfstack.h>
# ifdef NDEBUG
# define UA_RCU_LOCK() rcu_read_lock()
# define UA_RCU_UNLOCK() rcu_read_unlock()
# define UA_ASSERT_RCU_LOCKED()
# define UA_ASSERT_RCU_UNLOCKED()
# else
extern UA_THREAD_LOCAL bool rcu_locked;
# define UA_ASSERT_RCU_LOCKED() assert(rcu_locked)
# define UA_ASSERT_RCU_UNLOCKED() assert(!rcu_locked)
# define UA_RCU_LOCK() do { \
UA_ASSERT_RCU_UNLOCKED(); \
rcu_locked = true; \
rcu_read_lock(); } while(0)
# define UA_RCU_UNLOCK() do { \
UA_ASSERT_RCU_LOCKED(); \
rcu_locked = false; \
rcu_read_lock(); } while(0)
# endif
#else
# define UA_RCU_LOCK()
# define UA_RCU_UNLOCK()
# define UA_ASSERT_RCU_LOCKED()
# define UA_ASSERT_RCU_UNLOCKED()
#endif
/*********************************** amalgamated original file "/home/wn/Sources/open62541-open62541-395ce48/src/ua_types_encoding_binary.h" ***********************************/
typedef UA_StatusCode (*UA_exchangeEncodeBuffer)(void *handle, UA_ByteString *buf, size_t offset);
UA_StatusCode
UA_encodeBinary(const void *src, const UA_DataType *type,
UA_exchangeEncodeBuffer exchangeBufferCallback, void *exchangeBufferCallbackHandle,
UA_ByteString *dst, size_t *offset) UA_FUNC_ATTR_WARN_UNUSED_RESULT;
UA_StatusCode
UA_decodeBinary(const UA_ByteString *src, size_t *offset, void *dst,
const UA_DataType *type) UA_FUNC_ATTR_WARN_UNUSED_RESULT;
size_t UA_calcSizeBinary(void *p, const UA_DataType *type);
/*********************************** amalgamated original file "/home/wn/Sources/open62541-open62541-395ce48/build/src_generated/ua_types_generated_encoding_binary.h" ***********************************/
/* Generated from Opc.Ua.Types.bsd with script /home/wn/Sources/open62541-open62541-395ce48/tools/generate_datatypes.py
* on host debianX by user wn at 2016-06-07 04:48:38 */
/* Boolean */
static UA_INLINE UA_StatusCode UA_Boolean_encodeBinary(const UA_Boolean *src, UA_ByteString *dst, size_t *offset) { return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_BOOLEAN], NULL, NULL, dst, offset); }
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]); }
/* SByte */
static UA_INLINE UA_StatusCode UA_SByte_encodeBinary(const UA_SByte *src, UA_ByteString *dst, size_t *offset) { return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_SBYTE], NULL, NULL, dst, offset); }
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]); }
/* Byte */
static UA_INLINE UA_StatusCode UA_Byte_encodeBinary(const UA_Byte *src, UA_ByteString *dst, size_t *offset) { return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_BYTE], NULL, NULL, dst, offset); }
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]); }
/* Int16 */
static UA_INLINE UA_StatusCode UA_Int16_encodeBinary(const UA_Int16 *src, UA_ByteString *dst, size_t *offset) { return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_INT16], NULL, NULL, dst, offset); }
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]); }
/* UInt16 */
static UA_INLINE UA_StatusCode UA_UInt16_encodeBinary(const UA_UInt16 *src, UA_ByteString *dst, size_t *offset) { return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_UINT16], NULL, NULL, dst, offset); }
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]); }
/* Int32 */
static UA_INLINE UA_StatusCode UA_Int32_encodeBinary(const UA_Int32 *src, UA_ByteString *dst, size_t *offset) { return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_INT32], NULL, NULL, dst, offset); }
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]); }
/* UInt32 */
static UA_INLINE UA_StatusCode UA_UInt32_encodeBinary(const UA_UInt32 *src, UA_ByteString *dst, size_t *offset) { return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_UINT32], NULL, NULL, dst, offset); }
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]); }
/* Int64 */
static UA_INLINE UA_StatusCode UA_Int64_encodeBinary(const UA_Int64 *src, UA_ByteString *dst, size_t *offset) { return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_INT64], NULL, NULL, dst, offset); }
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]); }
/* UInt64 */
static UA_INLINE UA_StatusCode UA_UInt64_encodeBinary(const UA_UInt64 *src, UA_ByteString *dst, size_t *offset) { return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_UINT64], NULL, NULL, dst, offset); }
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]); }
/* Float */
static UA_INLINE UA_StatusCode UA_Float_encodeBinary(const UA_Float *src, UA_ByteString *dst, size_t *offset) { return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_FLOAT], NULL, NULL, dst, offset); }
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]); }
/* Double */
static UA_INLINE UA_StatusCode UA_Double_encodeBinary(const UA_Double *src, UA_ByteString *dst, size_t *offset) { return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_DOUBLE], NULL, NULL, dst, offset); }
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]); }
/* String */
static UA_INLINE UA_StatusCode UA_String_encodeBinary(const UA_String *src, UA_ByteString *dst, size_t *offset) { return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_STRING], NULL, NULL, dst, offset); }
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]); }
/* DateTime */
static UA_INLINE UA_StatusCode UA_DateTime_encodeBinary(const UA_DateTime *src, UA_ByteString *dst, size_t *offset) { return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_DATETIME], NULL, NULL, dst, offset); }
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]); }
/* Guid */
static UA_INLINE UA_StatusCode UA_Guid_encodeBinary(const UA_Guid *src, UA_ByteString *dst, size_t *offset) { return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_GUID], NULL, NULL, dst, offset); }
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]); }
/* ByteString */
static UA_INLINE UA_StatusCode UA_ByteString_encodeBinary(const UA_ByteString *src, UA_ByteString *dst, size_t *offset) { return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_BYTESTRING], NULL, NULL, dst, offset); }
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]); }
/* XmlElement */
static UA_INLINE UA_StatusCode UA_XmlElement_encodeBinary(const UA_XmlElement *src, UA_ByteString *dst, size_t *offset) { return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_XMLELEMENT], NULL, NULL, dst, offset); }
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]); }
/* NodeId */
static UA_INLINE UA_StatusCode UA_NodeId_encodeBinary(const UA_NodeId *src, UA_ByteString *dst, size_t *offset) { return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_NODEID], NULL, NULL, dst, offset); }
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]); }
/* ExpandedNodeId */
static UA_INLINE UA_StatusCode UA_ExpandedNodeId_encodeBinary(const UA_ExpandedNodeId *src, UA_ByteString *dst, size_t *offset) { return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_EXPANDEDNODEID], NULL, NULL, dst, offset); }
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]); }
/* StatusCode */
static UA_INLINE UA_StatusCode UA_StatusCode_encodeBinary(const UA_StatusCode *src, UA_ByteString *dst, size_t *offset) { return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_STATUSCODE], NULL, NULL, dst, offset); }
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]); }
/* QualifiedName */
static UA_INLINE UA_StatusCode UA_QualifiedName_encodeBinary(const UA_QualifiedName *src, UA_ByteString *dst, size_t *offset) { return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_QUALIFIEDNAME], NULL, NULL, dst, offset); }
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]); }
/* LocalizedText */
static UA_INLINE UA_StatusCode UA_LocalizedText_encodeBinary(const UA_LocalizedText *src, UA_ByteString *dst, size_t *offset) { return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_LOCALIZEDTEXT], NULL, NULL, dst, offset); }
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]); }
/* ExtensionObject */
static UA_INLINE UA_StatusCode UA_ExtensionObject_encodeBinary(const UA_ExtensionObject *src, UA_ByteString *dst, size_t *offset) { return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_EXTENSIONOBJECT], NULL, NULL, dst, offset); }
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]); }
/* DataValue */
static UA_INLINE UA_StatusCode UA_DataValue_encodeBinary(const UA_DataValue *src, UA_ByteString *dst, size_t *offset) { return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_DATAVALUE], NULL, NULL, dst, offset); }
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]); }
/* Variant */
static UA_INLINE UA_StatusCode UA_Variant_encodeBinary(const UA_Variant *src, UA_ByteString *dst, size_t *offset) { return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_VARIANT], NULL, NULL, dst, offset); }
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]); }
/* DiagnosticInfo */
static UA_INLINE UA_StatusCode UA_DiagnosticInfo_encodeBinary(const UA_DiagnosticInfo *src, UA_ByteString *dst, size_t *offset) { return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_DIAGNOSTICINFO], NULL, NULL, dst, offset); }
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]); }
/* SignedSoftwareCertificate */
static UA_INLINE UA_StatusCode UA_SignedSoftwareCertificate_encodeBinary(const UA_SignedSoftwareCertificate *src, UA_ByteString *dst, size_t *offset) { return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_SIGNEDSOFTWARECERTIFICATE], NULL, NULL, dst, offset); }
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]); }
/* BrowsePathTarget */
static UA_INLINE UA_StatusCode UA_BrowsePathTarget_encodeBinary(const UA_BrowsePathTarget *src, UA_ByteString *dst, size_t *offset) { return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_BROWSEPATHTARGET], NULL, NULL, dst, offset); }
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]); }
/* ViewAttributes */
static UA_INLINE UA_StatusCode UA_ViewAttributes_encodeBinary(const UA_ViewAttributes *src, UA_ByteString *dst, size_t *offset) { return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_VIEWATTRIBUTES], NULL, NULL, dst, offset); }
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]); }
/* BrowseResultMask */
static UA_INLINE UA_StatusCode UA_BrowseResultMask_encodeBinary(const UA_BrowseResultMask *src, UA_ByteString *dst, size_t *offset) { return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_BROWSERESULTMASK], NULL, NULL, dst, offset); }
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]); }
/* RequestHeader */
static UA_INLINE UA_StatusCode UA_RequestHeader_encodeBinary(const UA_RequestHeader *src, UA_ByteString *dst, size_t *offset) { return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_REQUESTHEADER], NULL, NULL, dst, offset); }
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]); }
/* MonitoredItemModifyResult */
static UA_INLINE UA_StatusCode UA_MonitoredItemModifyResult_encodeBinary(const UA_MonitoredItemModifyResult *src, UA_ByteString *dst, size_t *offset) { return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_MONITOREDITEMMODIFYRESULT], NULL, NULL, dst, offset); }
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]); }
/* ViewDescription */
static UA_INLINE UA_StatusCode UA_ViewDescription_encodeBinary(const UA_ViewDescription *src, UA_ByteString *dst, size_t *offset) { return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_VIEWDESCRIPTION], NULL, NULL, dst, offset); }
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]); }
/* CloseSecureChannelRequest */
static UA_INLINE UA_StatusCode UA_CloseSecureChannelRequest_encodeBinary(const UA_CloseSecureChannelRequest *src, UA_ByteString *dst, size_t *offset) { return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_CLOSESECURECHANNELREQUEST], NULL, NULL, dst, offset); }
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]); }
/* AddNodesResult */
static UA_INLINE UA_StatusCode UA_AddNodesResult_encodeBinary(const UA_AddNodesResult *src, UA_ByteString *dst, size_t *offset) { return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_ADDNODESRESULT], NULL, NULL, dst, offset); }
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]); }
/* VariableAttributes */
static UA_INLINE UA_StatusCode UA_VariableAttributes_encodeBinary(const UA_VariableAttributes *src, UA_ByteString *dst, size_t *offset) { return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES], NULL, NULL, dst, offset); }
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]); }
/* NotificationMessage */
static UA_INLINE UA_StatusCode UA_NotificationMessage_encodeBinary(const UA_NotificationMessage *src, UA_ByteString *dst, size_t *offset) { return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_NOTIFICATIONMESSAGE], NULL, NULL, dst, offset); }
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]); }
/* NodeAttributesMask */
static UA_INLINE UA_StatusCode UA_NodeAttributesMask_encodeBinary(const UA_NodeAttributesMask *src, UA_ByteString *dst, size_t *offset) { return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_NODEATTRIBUTESMASK], NULL, NULL, dst, offset); }
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]); }
/* MonitoringMode */
static UA_INLINE UA_StatusCode UA_MonitoringMode_encodeBinary(const UA_MonitoringMode *src, UA_ByteString *dst, size_t *offset) { return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_MONITORINGMODE], NULL, NULL, dst, offset); }
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]); }
/* CallMethodResult */
static UA_INLINE UA_StatusCode UA_CallMethodResult_encodeBinary(const UA_CallMethodResult *src, UA_ByteString *dst, size_t *offset) { return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_CALLMETHODRESULT], NULL, NULL, dst, offset); }
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]); }
/* ParsingResult */
static UA_INLINE UA_StatusCode UA_ParsingResult_encodeBinary(const UA_ParsingResult *src, UA_ByteString *dst, size_t *offset) { return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_PARSINGRESULT], NULL, NULL, dst, offset); }
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]); }
/* RelativePathElement */
static UA_INLINE UA_StatusCode UA_RelativePathElement_encodeBinary(const UA_RelativePathElement *src, UA_ByteString *dst, size_t *offset) { return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_RELATIVEPATHELEMENT], NULL, NULL, dst, offset); }
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]); }
/* BrowseDirection */
static UA_INLINE UA_StatusCode UA_BrowseDirection_encodeBinary(const UA_BrowseDirection *src, UA_ByteString *dst, size_t *offset) { return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_BROWSEDIRECTION], NULL, NULL, dst, offset); }
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]); }
/* CallMethodRequest */
static UA_INLINE UA_StatusCode UA_CallMethodRequest_encodeBinary(const UA_CallMethodRequest *src, UA_ByteString *dst, size_t *offset) { return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_CALLMETHODREQUEST], NULL, NULL, dst, offset); }
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]); }
/* ServerState */
static UA_INLINE UA_StatusCode UA_ServerState_encodeBinary(const UA_ServerState *src, UA_ByteString *dst, size_t *offset) { return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_SERVERSTATE], NULL, NULL, dst, offset); }
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]); }
/* UnregisterNodesRequest */
static UA_INLINE UA_StatusCode UA_UnregisterNodesRequest_encodeBinary(const UA_UnregisterNodesRequest *src, UA_ByteString *dst, size_t *offset) { return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_UNREGISTERNODESREQUEST], NULL, NULL, dst, offset); }
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]); }
/* ContentFilterElementResult */
static UA_INLINE UA_StatusCode UA_ContentFilterElementResult_encodeBinary(const UA_ContentFilterElementResult *src, UA_ByteString *dst, size_t *offset) { return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_CONTENTFILTERELEMENTRESULT], NULL, NULL, dst, offset); }
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]); }
/* QueryDataSet */
static UA_INLINE UA_StatusCode UA_QueryDataSet_encodeBinary(const UA_QueryDataSet *src, UA_ByteString *dst, size_t *offset) { return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_QUERYDATASET], NULL, NULL, dst, offset); }
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]); }
/* SetPublishingModeRequest */
static UA_INLINE UA_StatusCode UA_SetPublishingModeRequest_encodeBinary(const UA_SetPublishingModeRequest *src, UA_ByteString *dst, size_t *offset) { return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_SETPUBLISHINGMODEREQUEST], NULL, NULL, dst, offset); }
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]); }
/* TimestampsToReturn */
static UA_INLINE UA_StatusCode UA_TimestampsToReturn_encodeBinary(const UA_TimestampsToReturn *src, UA_ByteString *dst, size_t *offset) { return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_TIMESTAMPSTORETURN], NULL, NULL, dst, offset); }
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]); }
/* CallRequest */
static UA_INLINE UA_StatusCode UA_CallRequest_encodeBinary(const UA_CallRequest *src, UA_ByteString *dst, size_t *offset) { return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_CALLREQUEST], NULL, NULL, dst, offset); }
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]); }
/* MethodAttributes */
static UA_INLINE UA_StatusCode UA_MethodAttributes_encodeBinary(const UA_MethodAttributes *src, UA_ByteString *dst, size_t *offset) { return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_METHODATTRIBUTES], NULL, NULL, dst, offset); }
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]); }
/* DeleteReferencesItem */
static UA_INLINE UA_StatusCode UA_DeleteReferencesItem_encodeBinary(const UA_DeleteReferencesItem *src, UA_ByteString *dst, size_t *offset) { return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_DELETEREFERENCESITEM], NULL, NULL, dst, offset); }
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]); }
/* WriteValue */
static UA_INLINE UA_StatusCode UA_WriteValue_encodeBinary(const UA_WriteValue *src, UA_ByteString *dst, size_t *offset) { return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_WRITEVALUE], NULL, NULL, dst, offset); }
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]); }
/* MonitoredItemCreateResult */
static UA_INLINE UA_StatusCode UA_MonitoredItemCreateResult_encodeBinary(const UA_MonitoredItemCreateResult *src, UA_ByteString *dst, size_t *offset) { return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_MONITOREDITEMCREATERESULT], NULL, NULL, dst, offset); }
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]); }
/* MessageSecurityMode */
static UA_INLINE UA_StatusCode UA_MessageSecurityMode_encodeBinary(const UA_MessageSecurityMode *src, UA_ByteString *dst, size_t *offset) { return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_MESSAGESECURITYMODE], NULL, NULL, dst, offset); }
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]); }
/* MonitoringParameters */
static UA_INLINE UA_StatusCode UA_MonitoringParameters_encodeBinary(const UA_MonitoringParameters *src, UA_ByteString *dst, size_t *offset) { return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_MONITORINGPARAMETERS], NULL, NULL, dst, offset); }
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]); }
/* SignatureData */
static UA_INLINE UA_StatusCode UA_SignatureData_encodeBinary(const UA_SignatureData *src, UA_ByteString *dst, size_t *offset) { return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_SIGNATUREDATA], NULL, NULL, dst, offset); }
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]); }
/* ReferenceNode */
static UA_INLINE UA_StatusCode UA_ReferenceNode_encodeBinary(const UA_ReferenceNode *src, UA_ByteString *dst, size_t *offset) { return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_REFERENCENODE], NULL, NULL, dst, offset); }
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]); }
/* Argument */
static UA_INLINE UA_StatusCode UA_Argument_encodeBinary(const UA_Argument *src, UA_ByteString *dst, size_t *offset) { return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_ARGUMENT], NULL, NULL, dst, offset); }
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]); }
/* UserIdentityToken */
static UA_INLINE UA_StatusCode UA_UserIdentityToken_encodeBinary(const UA_UserIdentityToken *src, UA_ByteString *dst, size_t *offset) { return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_USERIDENTITYTOKEN], NULL, NULL, dst, offset); }
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]); }
/* ObjectTypeAttributes */
static UA_INLINE UA_StatusCode UA_ObjectTypeAttributes_encodeBinary(const UA_ObjectTypeAttributes *src, UA_ByteString *dst, size_t *offset) { return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_OBJECTTYPEATTRIBUTES], NULL, NULL, dst, offset); }
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]); }
/* SecurityTokenRequestType */
static UA_INLINE UA_StatusCode UA_SecurityTokenRequestType_encodeBinary(const UA_SecurityTokenRequestType *src, UA_ByteString *dst, size_t *offset) { return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_SECURITYTOKENREQUESTTYPE], NULL, NULL, dst, offset); }
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]); }
/* BuildInfo */
static UA_INLINE UA_StatusCode UA_BuildInfo_encodeBinary(const UA_BuildInfo *src, UA_ByteString *dst, size_t *offset) { return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_BUILDINFO], NULL, NULL, dst, offset); }
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]); }
/* NodeClass */
static UA_INLINE UA_StatusCode UA_NodeClass_encodeBinary(const UA_NodeClass *src, UA_ByteString *dst, size_t *offset) { return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_NODECLASS], NULL, NULL, dst, offset); }
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]); }
/* ChannelSecurityToken */
static UA_INLINE UA_StatusCode UA_ChannelSecurityToken_encodeBinary(const UA_ChannelSecurityToken *src, UA_ByteString *dst, size_t *offset) { return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_CHANNELSECURITYTOKEN], NULL, NULL, dst, offset); }
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]); }
/* MonitoredItemNotification */
static UA_INLINE UA_StatusCode UA_MonitoredItemNotification_encodeBinary(const UA_MonitoredItemNotification *src, UA_ByteString *dst, size_t *offset) { return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_MONITOREDITEMNOTIFICATION], NULL, NULL, dst, offset); }
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]); }
/* DeleteNodesItem */
static UA_INLINE UA_StatusCode UA_DeleteNodesItem_encodeBinary(const UA_DeleteNodesItem *src, UA_ByteString *dst, size_t *offset) { return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_DELETENODESITEM], NULL, NULL, dst, offset); }
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]); }
/* SubscriptionAcknowledgement */
static UA_INLINE UA_StatusCode UA_SubscriptionAcknowledgement_encodeBinary(const UA_SubscriptionAcknowledgement *src, UA_ByteString *dst, size_t *offset) { return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_SUBSCRIPTIONACKNOWLEDGEMENT], NULL, NULL, dst, offset); }
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]); }
/* ReadValueId */
static UA_INLINE UA_StatusCode UA_ReadValueId_encodeBinary(const UA_ReadValueId *src, UA_ByteString *dst, size_t *offset) { return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_READVALUEID], NULL, NULL, dst, offset); }
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]); }
/* AnonymousIdentityToken */
static UA_INLINE UA_StatusCode UA_AnonymousIdentityToken_encodeBinary(const UA_AnonymousIdentityToken *src, UA_ByteString *dst, size_t *offset) { return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_ANONYMOUSIDENTITYTOKEN], NULL, NULL, dst, offset); }
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]); }
/* DataTypeAttributes */
static UA_INLINE UA_StatusCode UA_DataTypeAttributes_encodeBinary(const UA_DataTypeAttributes *src, UA_ByteString *dst, size_t *offset) { return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_DATATYPEATTRIBUTES], NULL, NULL, dst, offset); }
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]); }
/* ResponseHeader */
static UA_INLINE UA_StatusCode UA_ResponseHeader_encodeBinary(const UA_ResponseHeader *src, UA_ByteString *dst, size_t *offset) { return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_RESPONSEHEADER], NULL, NULL, dst, offset); }
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]); }
/* DeleteSubscriptionsRequest */
static UA_INLINE UA_StatusCode UA_DeleteSubscriptionsRequest_encodeBinary(const UA_DeleteSubscriptionsRequest *src, UA_ByteString *dst, size_t *offset) { return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_DELETESUBSCRIPTIONSREQUEST], NULL, NULL, dst, offset); }
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]); }
/* DataChangeNotification */
static UA_INLINE UA_StatusCode UA_DataChangeNotification_encodeBinary(const UA_DataChangeNotification *src, UA_ByteString *dst, size_t *offset) { return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_DATACHANGENOTIFICATION], NULL, NULL, dst, offset); }
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]); }
/* DeleteMonitoredItemsResponse */
static UA_INLINE UA_StatusCode UA_DeleteMonitoredItemsResponse_encodeBinary(const UA_DeleteMonitoredItemsResponse *src, UA_ByteString *dst, size_t *offset) { return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_DELETEMONITOREDITEMSRESPONSE], NULL, NULL, dst, offset); }
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]); }
/* RelativePath */
static UA_INLINE UA_StatusCode UA_RelativePath_encodeBinary(const UA_RelativePath *src, UA_ByteString *dst, size_t *offset) { return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_RELATIVEPATH], NULL, NULL, dst, offset); }
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]); }
/* RegisterNodesRequest */
static UA_INLINE UA_StatusCode UA_RegisterNodesRequest_encodeBinary(const UA_RegisterNodesRequest *src, UA_ByteString *dst, size_t *offset) { return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_REGISTERNODESREQUEST], NULL, NULL, dst, offset); }
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]); }
/* DeleteNodesRequest */
static UA_INLINE UA_StatusCode UA_DeleteNodesRequest_encodeBinary(const UA_DeleteNodesRequest *src, UA_ByteString *dst, size_t *offset) { return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_DELETENODESREQUEST], NULL, NULL, dst, offset); }
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]); }
/* PublishResponse */
static UA_INLINE UA_StatusCode UA_PublishResponse_encodeBinary(const UA_PublishResponse *src, UA_ByteString *dst, size_t *offset) { return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_PUBLISHRESPONSE], NULL, NULL, dst, offset); }
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]); }
/* MonitoredItemModifyRequest */
static UA_INLINE UA_StatusCode UA_MonitoredItemModifyRequest_encodeBinary(const UA_MonitoredItemModifyRequest *src, UA_ByteString *dst, size_t *offset) { return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_MONITOREDITEMMODIFYREQUEST], NULL, NULL, dst, offset); }
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]); }
/* UserNameIdentityToken */
static UA_INLINE UA_StatusCode UA_UserNameIdentityToken_encodeBinary(const UA_UserNameIdentityToken *src, UA_ByteString *dst, size_t *offset) { return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_USERNAMEIDENTITYTOKEN], NULL, NULL, dst, offset); }
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]); }
/* IdType */
static UA_INLINE UA_StatusCode UA_IdType_encodeBinary(const UA_IdType *src, UA_ByteString *dst, size_t *offset) { return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_IDTYPE], NULL, NULL, dst, offset); }
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]); }
/* UserTokenType */
static UA_INLINE UA_StatusCode UA_UserTokenType_encodeBinary(const UA_UserTokenType *src, UA_ByteString *dst, size_t *offset) { return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_USERTOKENTYPE], NULL, NULL, dst, offset); }
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]); }
/* NodeAttributes */
static UA_INLINE UA_StatusCode UA_NodeAttributes_encodeBinary(const UA_NodeAttributes *src, UA_ByteString *dst, size_t *offset) { return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_NODEATTRIBUTES], NULL, NULL, dst, offset); }
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]); }
/* ActivateSessionRequest */
static UA_INLINE UA_StatusCode UA_ActivateSessionRequest_encodeBinary(const UA_ActivateSessionRequest *src, UA_ByteString *dst, size_t *offset) { return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_ACTIVATESESSIONREQUEST], NULL, NULL, dst, offset); }
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]); }
/* OpenSecureChannelResponse */
static UA_INLINE UA_StatusCode UA_OpenSecureChannelResponse_encodeBinary(const UA_OpenSecureChannelResponse *src, UA_ByteString *dst, size_t *offset) { return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_OPENSECURECHANNELRESPONSE], NULL, NULL, dst, offset); }
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]); }
/* ApplicationType */
static UA_INLINE UA_StatusCode UA_ApplicationType_encodeBinary(const UA_ApplicationType *src, UA_ByteString *dst, size_t *offset) { return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_APPLICATIONTYPE], NULL, NULL, dst, offset); }
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]); }
/* QueryNextResponse */
static UA_INLINE UA_StatusCode UA_QueryNextResponse_encodeBinary(const UA_QueryNextResponse *src, UA_ByteString *dst, size_t *offset) { return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_QUERYNEXTRESPONSE], NULL, NULL, dst, offset); }
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]); }
/* ActivateSessionResponse */
static UA_INLINE UA_StatusCode UA_ActivateSessionResponse_encodeBinary(const UA_ActivateSessionResponse *src, UA_ByteString *dst, size_t *offset) { return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_ACTIVATESESSIONRESPONSE], NULL, NULL, dst, offset); }
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]); }
/* FilterOperator */
static UA_INLINE UA_StatusCode UA_FilterOperator_encodeBinary(const UA_FilterOperator *src, UA_ByteString *dst, size_t *offset) { return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_FILTEROPERATOR], NULL, NULL, dst, offset); }
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]); }
/* QueryNextRequest */
static UA_INLINE UA_StatusCode UA_QueryNextRequest_encodeBinary(const UA_QueryNextRequest *src, UA_ByteString *dst, size_t *offset) { return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_QUERYNEXTREQUEST], NULL, NULL, dst, offset); }
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]); }
/* BrowseNextRequest */
static UA_INLINE UA_StatusCode UA_BrowseNextRequest_encodeBinary(const UA_BrowseNextRequest *src, UA_ByteString *dst, size_t *offset) { return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_BROWSENEXTREQUEST], NULL, NULL, dst, offset); }
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]); }
/* CreateSubscriptionRequest */
static UA_INLINE UA_StatusCode UA_CreateSubscriptionRequest_encodeBinary(const UA_CreateSubscriptionRequest *src, UA_ByteString *dst, size_t *offset) { return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_CREATESUBSCRIPTIONREQUEST], NULL, NULL, dst, offset); }
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]); }
/* VariableTypeAttributes */
static UA_INLINE UA_StatusCode UA_VariableTypeAttributes_encodeBinary(const UA_VariableTypeAttributes *src, UA_ByteString *dst, size_t *offset) { return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_VARIABLETYPEATTRIBUTES], NULL, NULL, dst, offset); }
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]); }
/* BrowsePathResult */
static UA_INLINE UA_StatusCode UA_BrowsePathResult_encodeBinary(const UA_BrowsePathResult *src, UA_ByteString *dst, size_t *offset) { return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_BROWSEPATHRESULT], NULL, NULL, dst, offset); }
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]); }
/* ModifySubscriptionResponse */
static UA_INLINE UA_StatusCode UA_ModifySubscriptionResponse_encodeBinary(const UA_ModifySubscriptionResponse *src, UA_ByteString *dst, size_t *offset) { return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_MODIFYSUBSCRIPTIONRESPONSE], NULL, NULL, dst, offset); }
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]); }
/* RegisterNodesResponse */
static UA_INLINE UA_StatusCode UA_RegisterNodesResponse_encodeBinary(const UA_RegisterNodesResponse *src, UA_ByteString *dst, size_t *offset) { return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_REGISTERNODESRESPONSE], NULL, NULL, dst, offset); }
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]); }
/* CloseSessionRequest */
static UA_INLINE UA_StatusCode UA_CloseSessionRequest_encodeBinary(const UA_CloseSessionRequest *src, UA_ByteString *dst, size_t *offset) { return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_CLOSESESSIONREQUEST], NULL, NULL, dst, offset); }
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]); }
/* ModifySubscriptionRequest */
static UA_INLINE UA_StatusCode UA_ModifySubscriptionRequest_encodeBinary(const UA_ModifySubscriptionRequest *src, UA_ByteString *dst, size_t *offset) { return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_MODIFYSUBSCRIPTIONREQUEST], NULL, NULL, dst, offset); }
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]); }
/* UserTokenPolicy */
static UA_INLINE UA_StatusCode UA_UserTokenPolicy_encodeBinary(const UA_UserTokenPolicy *src, UA_ByteString *dst, size_t *offset) { return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_USERTOKENPOLICY], NULL, NULL, dst, offset); }
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]); }
/* DeleteMonitoredItemsRequest */
static UA_INLINE UA_StatusCode UA_DeleteMonitoredItemsRequest_encodeBinary(const UA_DeleteMonitoredItemsRequest *src, UA_ByteString *dst, size_t *offset) { return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_DELETEMONITOREDITEMSREQUEST], NULL, NULL, dst, offset); }
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]); }
/* ReferenceTypeAttributes */
static UA_INLINE UA_StatusCode UA_ReferenceTypeAttributes_encodeBinary(const UA_ReferenceTypeAttributes *src, UA_ByteString *dst, size_t *offset) { return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_REFERENCETYPEATTRIBUTES], NULL, NULL, dst, offset); }
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]); }
/* BrowsePath */
static UA_INLINE UA_StatusCode UA_BrowsePath_encodeBinary(const UA_BrowsePath *src, UA_ByteString *dst, size_t *offset) { return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_BROWSEPATH], NULL, NULL, dst, offset); }
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]); }
/* UnregisterNodesResponse */
static UA_INLINE UA_StatusCode UA_UnregisterNodesResponse_encodeBinary(const UA_UnregisterNodesResponse *src, UA_ByteString *dst, size_t *offset) { return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_UNREGISTERNODESRESPONSE], NULL, NULL, dst, offset); }
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]); }
/* WriteRequest */
static UA_INLINE UA_StatusCode UA_WriteRequest_encodeBinary(const UA_WriteRequest *src, UA_ByteString *dst, size_t *offset) { return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_WRITEREQUEST], NULL, NULL, dst, offset); }
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]); }
/* ObjectAttributes */
static UA_INLINE UA_StatusCode UA_ObjectAttributes_encodeBinary(const UA_ObjectAttributes *src, UA_ByteString *dst, size_t *offset) { return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_OBJECTATTRIBUTES], NULL, NULL, dst, offset); }
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]); }
/* BrowseDescription */
static UA_INLINE UA_StatusCode UA_BrowseDescription_encodeBinary(const UA_BrowseDescription *src, UA_ByteString *dst, size_t *offset) { return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_BROWSEDESCRIPTION], NULL, NULL, dst, offset); }
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]); }
/* RepublishRequest */
static UA_INLINE UA_StatusCode UA_RepublishRequest_encodeBinary(const UA_RepublishRequest *src, UA_ByteString *dst, size_t *offset) { return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_REPUBLISHREQUEST], NULL, NULL, dst, offset); }
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]); }
/* GetEndpointsRequest */
static UA_INLINE UA_StatusCode UA_GetEndpointsRequest_encodeBinary(const UA_GetEndpointsRequest *src, UA_ByteString *dst, size_t *offset) { return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_GETENDPOINTSREQUEST], NULL, NULL, dst, offset); }
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]); }
/* PublishRequest */
static UA_INLINE UA_StatusCode UA_PublishRequest_encodeBinary(const UA_PublishRequest *src, UA_ByteString *dst, size_t *offset) { return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_PUBLISHREQUEST], NULL, NULL, dst, offset); }
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]); }
/* AddNodesResponse */
static UA_INLINE UA_StatusCode UA_AddNodesResponse_encodeBinary(const UA_AddNodesResponse *src, UA_ByteString *dst, size_t *offset) { return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_ADDNODESRESPONSE], NULL, NULL, dst, offset); }
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]); }
/* CloseSecureChannelResponse */
static UA_INLINE UA_StatusCode UA_CloseSecureChannelResponse_encodeBinary(const UA_CloseSecureChannelResponse *src, UA_ByteString *dst, size_t *offset) { return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_CLOSESECURECHANNELRESPONSE], NULL, NULL, dst, offset); }
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]); }
/* ModifyMonitoredItemsRequest */
static UA_INLINE UA_StatusCode UA_ModifyMonitoredItemsRequest_encodeBinary(const UA_ModifyMonitoredItemsRequest *src, UA_ByteString *dst, size_t *offset) { return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_MODIFYMONITOREDITEMSREQUEST], NULL, NULL, dst, offset); }
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]); }
/* FindServersRequest */
static UA_INLINE UA_StatusCode UA_FindServersRequest_encodeBinary(const UA_FindServersRequest *src, UA_ByteString *dst, size_t *offset) { return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_FINDSERVERSREQUEST], NULL, NULL, dst, offset); }
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]); }
/* ReferenceDescription */
static UA_INLINE UA_StatusCode UA_ReferenceDescription_encodeBinary(const UA_ReferenceDescription *src, UA_ByteString *dst, size_t *offset) { return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_REFERENCEDESCRIPTION], NULL, NULL, dst, offset); }
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]); }
/* SetPublishingModeResponse */
static UA_INLINE UA_StatusCode UA_SetPublishingModeResponse_encodeBinary(const UA_SetPublishingModeResponse *src, UA_ByteString *dst, size_t *offset) { return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_SETPUBLISHINGMODERESPONSE], NULL, NULL, dst, offset); }
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]); }
/* ContentFilterResult */
static UA_INLINE UA_StatusCode UA_ContentFilterResult_encodeBinary(const UA_ContentFilterResult *src, UA_ByteString *dst, size_t *offset) { return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_CONTENTFILTERRESULT], NULL, NULL, dst, offset); }
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]); }
/* AddReferencesItem */
static UA_INLINE UA_StatusCode UA_AddReferencesItem_encodeBinary(const UA_AddReferencesItem *src, UA_ByteString *dst, size_t *offset) { return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_ADDREFERENCESITEM], NULL, NULL, dst, offset); }
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]); }
/* QueryDataDescription */
static UA_INLINE UA_StatusCode UA_QueryDataDescription_encodeBinary(const UA_QueryDataDescription *src, UA_ByteString *dst, size_t *offset) { return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_QUERYDATADESCRIPTION], NULL, NULL, dst, offset); }
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]); }
/* CreateSubscriptionResponse */
static UA_INLINE UA_StatusCode UA_CreateSubscriptionResponse_encodeBinary(const UA_CreateSubscriptionResponse *src, UA_ByteString *dst, size_t *offset) { return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_CREATESUBSCRIPTIONRESPONSE], NULL, NULL, dst, offset); }
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]); }
/* DeleteSubscriptionsResponse */
static UA_INLINE UA_StatusCode UA_DeleteSubscriptionsResponse_encodeBinary(const UA_DeleteSubscriptionsResponse *src, UA_ByteString *dst, size_t *offset) { return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_DELETESUBSCRIPTIONSRESPONSE], NULL, NULL, dst, offset); }
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]); }
/* WriteResponse */
static UA_INLINE UA_StatusCode UA_WriteResponse_encodeBinary(const UA_WriteResponse *src, UA_ByteString *dst, size_t *offset) { return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_WRITERESPONSE], NULL, NULL, dst, offset); }
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]); }
/* DeleteReferencesResponse */
static UA_INLINE UA_StatusCode UA_DeleteReferencesResponse_encodeBinary(const UA_DeleteReferencesResponse *src, UA_ByteString *dst, size_t *offset) { return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_DELETEREFERENCESRESPONSE], NULL, NULL, dst, offset); }
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]); }
/* CreateMonitoredItemsResponse */
static UA_INLINE UA_StatusCode UA_CreateMonitoredItemsResponse_encodeBinary(const UA_CreateMonitoredItemsResponse *src, UA_ByteString *dst, size_t *offset) { return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_CREATEMONITOREDITEMSRESPONSE], NULL, NULL, dst, offset); }
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]); }
/* CallResponse */
static UA_INLINE UA_StatusCode UA_CallResponse_encodeBinary(const UA_CallResponse *src, UA_ByteString *dst, size_t *offset) { return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_CALLRESPONSE], NULL, NULL, dst, offset); }
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]); }
/* DeleteNodesResponse */
static UA_INLINE UA_StatusCode UA_DeleteNodesResponse_encodeBinary(const UA_DeleteNodesResponse *src, UA_ByteString *dst, size_t *offset) { return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_DELETENODESRESPONSE], NULL, NULL, dst, offset); }
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]); }
/* RepublishResponse */
static UA_INLINE UA_StatusCode UA_RepublishResponse_encodeBinary(const UA_RepublishResponse *src, UA_ByteString *dst, size_t *offset) { return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_REPUBLISHRESPONSE], NULL, NULL, dst, offset); }
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]); }
/* MonitoredItemCreateRequest */
static UA_INLINE UA_StatusCode UA_MonitoredItemCreateRequest_encodeBinary(const UA_MonitoredItemCreateRequest *src, UA_ByteString *dst, size_t *offset) { return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_MONITOREDITEMCREATEREQUEST], NULL, NULL, dst, offset); }
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]); }
/* DeleteReferencesRequest */
static UA_INLINE UA_StatusCode UA_DeleteReferencesRequest_encodeBinary(const UA_DeleteReferencesRequest *src, UA_ByteString *dst, size_t *offset) { return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_DELETEREFERENCESREQUEST], NULL, NULL, dst, offset); }
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]); }
/* ModifyMonitoredItemsResponse */
static UA_INLINE UA_StatusCode UA_ModifyMonitoredItemsResponse_encodeBinary(const UA_ModifyMonitoredItemsResponse *src, UA_ByteString *dst, size_t *offset) { return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_MODIFYMONITOREDITEMSRESPONSE], NULL, NULL, dst, offset); }
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]); }
/* ReadResponse */
static UA_INLINE UA_StatusCode UA_ReadResponse_encodeBinary(const UA_ReadResponse *src, UA_ByteString *dst, size_t *offset) { return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_READRESPONSE], NULL, NULL, dst, offset); }
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]); }
/* AddReferencesRequest */
static UA_INLINE UA_StatusCode UA_AddReferencesRequest_encodeBinary(const UA_AddReferencesRequest *src, UA_ByteString *dst, size_t *offset) { return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_ADDREFERENCESREQUEST], NULL, NULL, dst, offset); }
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]); }
/* ReadRequest */
static UA_INLINE UA_StatusCode UA_ReadRequest_encodeBinary(const UA_ReadRequest *src, UA_ByteString *dst, size_t *offset) { return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_READREQUEST], NULL, NULL, dst, offset); }
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]); }
/* OpenSecureChannelRequest */
static UA_INLINE UA_StatusCode UA_OpenSecureChannelRequest_encodeBinary(const UA_OpenSecureChannelRequest *src, UA_ByteString *dst, size_t *offset) { return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_OPENSECURECHANNELREQUEST], NULL, NULL, dst, offset); }
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]); }
/* AddNodesItem */
static UA_INLINE UA_StatusCode UA_AddNodesItem_encodeBinary(const UA_AddNodesItem *src, UA_ByteString *dst, size_t *offset) { return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_ADDNODESITEM], NULL, NULL, dst, offset); }
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]); }
/* ApplicationDescription */
static UA_INLINE UA_StatusCode UA_ApplicationDescription_encodeBinary(const UA_ApplicationDescription *src, UA_ByteString *dst, size_t *offset) { return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_APPLICATIONDESCRIPTION], NULL, NULL, dst, offset); }
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]); }
/* NodeTypeDescription */
static UA_INLINE UA_StatusCode UA_NodeTypeDescription_encodeBinary(const UA_NodeTypeDescription *src, UA_ByteString *dst, size_t *offset) { return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_NODETYPEDESCRIPTION], NULL, NULL, dst, offset); }
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]); }
/* FindServersResponse */
static UA_INLINE UA_StatusCode UA_FindServersResponse_encodeBinary(const UA_FindServersResponse *src, UA_ByteString *dst, size_t *offset) { return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_FINDSERVERSRESPONSE], NULL, NULL, dst, offset); }
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]); }
/* ServerStatusDataType */
static UA_INLINE UA_StatusCode UA_ServerStatusDataType_encodeBinary(const UA_ServerStatusDataType *src, UA_ByteString *dst, size_t *offset) { return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_SERVERSTATUSDATATYPE], NULL, NULL, dst, offset); }
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]); }
/* AddReferencesResponse */
static UA_INLINE UA_StatusCode UA_AddReferencesResponse_encodeBinary(const UA_AddReferencesResponse *src, UA_ByteString *dst, size_t *offset) { return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_ADDREFERENCESRESPONSE], NULL, NULL, dst, offset); }
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]); }
/* TranslateBrowsePathsToNodeIdsResponse */
static UA_INLINE UA_StatusCode UA_TranslateBrowsePathsToNodeIdsResponse_encodeBinary(const UA_TranslateBrowsePathsToNodeIdsResponse *src, UA_ByteString *dst, size_t *offset) { return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_TRANSLATEBROWSEPATHSTONODEIDSRESPONSE], NULL, NULL, dst, offset); }
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]); }
/* ContentFilterElement */
static UA_INLINE UA_StatusCode UA_ContentFilterElement_encodeBinary(const UA_ContentFilterElement *src, UA_ByteString *dst, size_t *offset) { return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_CONTENTFILTERELEMENT], NULL, NULL, dst, offset); }
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]); }
/* TranslateBrowsePathsToNodeIdsRequest */
static UA_INLINE UA_StatusCode UA_TranslateBrowsePathsToNodeIdsRequest_encodeBinary(const UA_TranslateBrowsePathsToNodeIdsRequest *src, UA_ByteString *dst, size_t *offset) { return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_TRANSLATEBROWSEPATHSTONODEIDSREQUEST], NULL, NULL, dst, offset); }
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]); }
/* CloseSessionResponse */
static UA_INLINE UA_StatusCode UA_CloseSessionResponse_encodeBinary(const UA_CloseSessionResponse *src, UA_ByteString *dst, size_t *offset) { return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_CLOSESESSIONRESPONSE], NULL, NULL, dst, offset); }
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]); }
/* ServiceFault */
static UA_INLINE UA_StatusCode UA_ServiceFault_encodeBinary(const UA_ServiceFault *src, UA_ByteString *dst, size_t *offset) { return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_SERVICEFAULT], NULL, NULL, dst, offset); }
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]); }
/* CreateMonitoredItemsRequest */
static UA_INLINE UA_StatusCode UA_CreateMonitoredItemsRequest_encodeBinary(const UA_CreateMonitoredItemsRequest *src, UA_ByteString *dst, size_t *offset) { return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_CREATEMONITOREDITEMSREQUEST], NULL, NULL, dst, offset); }
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]); }
/* ContentFilter */
static UA_INLINE UA_StatusCode UA_ContentFilter_encodeBinary(const UA_ContentFilter *src, UA_ByteString *dst, size_t *offset) { return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_CONTENTFILTER], NULL, NULL, dst, offset); }
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]); }
/* QueryFirstResponse */
static UA_INLINE UA_StatusCode UA_QueryFirstResponse_encodeBinary(const UA_QueryFirstResponse *src, UA_ByteString *dst, size_t *offset) { return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_QUERYFIRSTRESPONSE], NULL, NULL, dst, offset); }
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]); }
/* AddNodesRequest */
static UA_INLINE UA_StatusCode UA_AddNodesRequest_encodeBinary(const UA_AddNodesRequest *src, UA_ByteString *dst, size_t *offset) { return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_ADDNODESREQUEST], NULL, NULL, dst, offset); }
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]); }
/* BrowseRequest */
static UA_INLINE UA_StatusCode UA_BrowseRequest_encodeBinary(const UA_BrowseRequest *src, UA_ByteString *dst, size_t *offset) { return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_BROWSEREQUEST], NULL, NULL, dst, offset); }
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]); }
/* BrowseResult */
static UA_INLINE UA_StatusCode UA_BrowseResult_encodeBinary(const UA_BrowseResult *src, UA_ByteString *dst, size_t *offset) { return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_BROWSERESULT], NULL, NULL, dst, offset); }
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]); }
/* CreateSessionRequest */
static UA_INLINE UA_StatusCode UA_CreateSessionRequest_encodeBinary(const UA_CreateSessionRequest *src, UA_ByteString *dst, size_t *offset) { return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_CREATESESSIONREQUEST], NULL, NULL, dst, offset); }
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]); }
/* EndpointDescription */
static UA_INLINE UA_StatusCode UA_EndpointDescription_encodeBinary(const UA_EndpointDescription *src, UA_ByteString *dst, size_t *offset) { return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_ENDPOINTDESCRIPTION], NULL, NULL, dst, offset); }
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]); }
/* GetEndpointsResponse */
static UA_INLINE UA_StatusCode UA_GetEndpointsResponse_encodeBinary(const UA_GetEndpointsResponse *src, UA_ByteString *dst, size_t *offset) { return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_GETENDPOINTSRESPONSE], NULL, NULL, dst, offset); }
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]); }
/* BrowseNextResponse */
static UA_INLINE UA_StatusCode UA_BrowseNextResponse_encodeBinary(const UA_BrowseNextResponse *src, UA_ByteString *dst, size_t *offset) { return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_BROWSENEXTRESPONSE], NULL, NULL, dst, offset); }
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]); }
/* BrowseResponse */
static UA_INLINE UA_StatusCode UA_BrowseResponse_encodeBinary(const UA_BrowseResponse *src, UA_ByteString *dst, size_t *offset) { return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_BROWSERESPONSE], NULL, NULL, dst, offset); }
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]); }
/* CreateSessionResponse */
static UA_INLINE UA_StatusCode UA_CreateSessionResponse_encodeBinary(const UA_CreateSessionResponse *src, UA_ByteString *dst, size_t *offset) { return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_CREATESESSIONRESPONSE], NULL, NULL, dst, offset); }
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]); }
/* QueryFirstRequest */
static UA_INLINE UA_StatusCode UA_QueryFirstRequest_encodeBinary(const UA_QueryFirstRequest *src, UA_ByteString *dst, size_t *offset) { return UA_encodeBinary(src, &UA_TYPES[UA_TYPES_QUERYFIRSTREQUEST], NULL, NULL, dst, offset); }
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]); }
/*********************************** amalgamated original file "/home/wn/Sources/open62541-open62541-395ce48/build/src_generated/ua_transport_generated.h" ***********************************/
/* Generated from Opc.Ua.Types.bsd, Custom.Opc.Ua.Transport.bsd with script /home/wn/Sources/open62541-open62541-395ce48/tools/generate_datatypes.py
* on host debianX by user wn at 2016-06-07 04:48:38 */
#ifdef __cplusplus
extern "C" {
#endif
#ifdef UA_INTERNAL
#endif
/**
* Additional Data Type Definitions
* ================================
*/
#define UA_TRANSPORT_COUNT 11
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
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
* -------------------------------
* Secure Conversation Message Footer */
typedef struct {
size_t paddingSize;
UA_Byte *padding;
UA_Byte signature;
} UA_SecureConversationMessageFooter;
#define UA_TRANSPORT_SECURECONVERSATIONMESSAGEFOOTER 1
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
* ---------------
* 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
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]); }
/**
* 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;
#define UA_TRANSPORT_MESSAGETYPE 3
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
* ---------------------------------
* Security Header */
typedef struct {
UA_ByteString securityPolicyUri;
UA_ByteString senderCertificate;
UA_ByteString receiverCertificateThumbprint;
} UA_AsymmetricAlgorithmSecurityHeader;
#define UA_TRANSPORT_ASYMMETRICALGORITHMSECURITYHEADER 4
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
* ---------------------
* 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 5
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
* --------------
* Secure Layer Sequence Header */
typedef struct {
UA_UInt32 sequenceNumber;
UA_UInt32 requestId;
} UA_SequenceHeader;
#define UA_TRANSPORT_SEQUENCEHEADER 6
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
* ----------------
* TCP Header */
typedef struct {
UA_UInt32 messageTypeAndChunkType;
UA_UInt32 messageSize;
} UA_TcpMessageHeader;
#define UA_TRANSPORT_TCPMESSAGEHEADER 7
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
* ---------
* Type of the chunk */
typedef enum {
UA_CHUNKTYPE_FINAL = 0x46000000,
UA_CHUNKTYPE_INTERMEDIATE = 0x43000000,
UA_CHUNKTYPE_ABORT = 0x41000000
} UA_ChunkType;
#define UA_TRANSPORT_CHUNKTYPE 8
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
* --------------------------------
* Secure Layer Symmetric Algorithm Header */
typedef struct {
UA_UInt32 tokenId;
} UA_SymmetricAlgorithmSecurityHeader;
#define UA_TRANSPORT_SYMMETRICALGORITHMSECURITYHEADER 9
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
* -------------------------------
* Secure Layer Sequence Header */
typedef struct {
UA_TcpMessageHeader messageHeader;
UA_UInt32 secureChannelId;
} UA_SecureConversationMessageHeader;
#define UA_TRANSPORT_SECURECONVERSATIONMESSAGEHEADER 10
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]); }
#ifdef __cplusplus
} // extern "C"
#endif
/*********************************** amalgamated original file "/home/wn/Sources/open62541-open62541-395ce48/build/src_generated/ua_transport_generated_encoding_binary.h" ***********************************/
/* Generated from Opc.Ua.Types.bsd, Custom.Opc.Ua.Transport.bsd with script /home/wn/Sources/open62541-open62541-395ce48/tools/generate_datatypes.py
* on host debianX by user wn at 2016-06-07 04:48:38 */
/* SecureConversationMessageAbortBody */
static UA_INLINE UA_StatusCode UA_SecureConversationMessageAbortBody_encodeBinary(const UA_SecureConversationMessageAbortBody *src, UA_ByteString *dst, size_t *offset) { return UA_encodeBinary(src, &UA_TRANSPORT[UA_TRANSPORT_SECURECONVERSATIONMESSAGEABORTBODY], NULL, NULL, dst, offset); }
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]); }
/* SecureConversationMessageFooter */
static UA_INLINE UA_StatusCode UA_SecureConversationMessageFooter_encodeBinary(const UA_SecureConversationMessageFooter *src, UA_ByteString *dst, size_t *offset) { return UA_encodeBinary(src, &UA_TRANSPORT[UA_TRANSPORT_SECURECONVERSATIONMESSAGEFOOTER], NULL, NULL, dst, offset); }
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]); }
/* TcpHelloMessage */
static UA_INLINE UA_StatusCode UA_TcpHelloMessage_encodeBinary(const UA_TcpHelloMessage *src, UA_ByteString *dst, size_t *offset) { return UA_encodeBinary(src, &UA_TRANSPORT[UA_TRANSPORT_TCPHELLOMESSAGE], NULL, NULL, dst, offset); }
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]); }
/* MessageType */
static UA_INLINE UA_StatusCode UA_MessageType_encodeBinary(const UA_MessageType *src, UA_ByteString *dst, size_t *offset) { return UA_encodeBinary(src, &UA_TRANSPORT[UA_TRANSPORT_MESSAGETYPE], NULL, NULL, dst, offset); }
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]); }
/* AsymmetricAlgorithmSecurityHeader */
static UA_INLINE UA_StatusCode UA_AsymmetricAlgorithmSecurityHeader_encodeBinary(const UA_AsymmetricAlgorithmSecurityHeader *src, UA_ByteString *dst, size_t *offset) { return UA_encodeBinary(src, &UA_TRANSPORT[UA_TRANSPORT_ASYMMETRICALGORITHMSECURITYHEADER], NULL, NULL, dst, offset); }
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]); }
/* TcpAcknowledgeMessage */
static UA_INLINE UA_StatusCode UA_TcpAcknowledgeMessage_encodeBinary(const UA_TcpAcknowledgeMessage *src, UA_ByteString *dst, size_t *offset) { return UA_encodeBinary(src, &UA_TRANSPORT[UA_TRANSPORT_TCPACKNOWLEDGEMESSAGE], NULL, NULL, dst, offset); }
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]); }
/* SequenceHeader */
static UA_INLINE UA_StatusCode UA_SequenceHeader_encodeBinary(const UA_SequenceHeader *src, UA_ByteString *dst, size_t *offset) { return UA_encodeBinary(src, &UA_TRANSPORT[UA_TRANSPORT_SEQUENCEHEADER], NULL, NULL, dst, offset); }
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]); }
/* TcpMessageHeader */
static UA_INLINE UA_StatusCode UA_TcpMessageHeader_encodeBinary(const UA_TcpMessageHeader *src, UA_ByteString *dst, size_t *offset) { return UA_encodeBinary(src, &UA_TRANSPORT[UA_TRANSPORT_TCPMESSAGEHEADER], NULL, NULL, dst, offset); }
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]); }
/* ChunkType */
static UA_INLINE UA_StatusCode UA_ChunkType_encodeBinary(const UA_ChunkType *src, UA_ByteString *dst, size_t *offset) { return UA_encodeBinary(src, &UA_TRANSPORT[UA_TRANSPORT_CHUNKTYPE], NULL, NULL, dst, offset); }
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]); }
/* SymmetricAlgorithmSecurityHeader */
static UA_INLINE UA_StatusCode UA_SymmetricAlgorithmSecurityHeader_encodeBinary(const UA_SymmetricAlgorithmSecurityHeader *src, UA_ByteString *dst, size_t *offset) { return UA_encodeBinary(src, &UA_TRANSPORT[UA_TRANSPORT_SYMMETRICALGORITHMSECURITYHEADER], NULL, NULL, dst, offset); }
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]); }
/* SecureConversationMessageHeader */
static UA_INLINE UA_StatusCode UA_SecureConversationMessageHeader_encodeBinary(const UA_SecureConversationMessageHeader *src, UA_ByteString *dst, size_t *offset) { return UA_encodeBinary(src, &UA_TRANSPORT[UA_TRANSPORT_SECURECONVERSATIONMESSAGEHEADER], NULL, NULL, dst, offset); }
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]); }
/*********************************** amalgamated original file "/home/wn/Sources/open62541-open62541-395ce48/src/ua_connection_internal.h" ***********************************/
/**
* The network layer may receive chopped up messages since TCP is a streaming
* protocol. Furthermore, the networklayer may operate on ringbuffers or
* statically assigned memory.
*
* If an entire message 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 message The received message. The content may be overwritten when a
* previsouly received buffer is completed.
* @param realloced The Boolean value is set to true if the outgoing message has
* been reallocated from the network layer.
* @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_completeMessages(UA_Connection *connection, UA_ByteString * UA_RESTRICT message,
UA_Boolean * UA_RESTRICT realloced);
void UA_EXPORT UA_Connection_detachSecureChannel(UA_Connection *connection);
void UA_EXPORT UA_Connection_attachSecureChannel(UA_Connection *connection, UA_SecureChannel *channel);
/*********************************** amalgamated original file "/home/wn/Sources/open62541-open62541-395ce48/src/ua_securechannel.h" ***********************************/
struct UA_Session;
typedef struct UA_Session UA_Session;
struct SessionEntry {
LIST_ENTRY(SessionEntry) pointers;
UA_Session *session; // Just a pointer. The session is held in the session manager or the client
};
/* For chunked requests */
struct ChunkEntry {
LIST_ENTRY(ChunkEntry) pointers;
UA_UInt32 requestId;
UA_Boolean invalid_message;
UA_ByteString bytes;
};
/* For chunked responses */
typedef struct {
UA_SecureChannel *channel;
UA_UInt32 requestId;
UA_UInt32 messageType;
UA_UInt16 chunksSoFar;
size_t messageSizeSoFar;
UA_Boolean final;
UA_Boolean abort;
} UA_ChunkInfo;
struct UA_SecureChannel {
UA_MessageSecurityMode securityMode;
UA_ChannelSecurityToken securityToken; // the channelId is contained in the securityToken
UA_ChannelSecurityToken nextSecurityToken; // the channelId is contained in the securityToken
UA_AsymmetricAlgorithmSecurityHeader clientAsymAlgSettings;
UA_AsymmetricAlgorithmSecurityHeader serverAsymAlgSettings;
UA_ByteString clientNonce;
UA_ByteString serverNonce;
UA_UInt32 sequenceNumber;
UA_Connection *connection;
LIST_HEAD(session_pointerlist, SessionEntry) sessions;
LIST_HEAD(chunk_pointerlist, ChunkEntry) chunks;
};
void UA_SecureChannel_init(UA_SecureChannel *channel);
void UA_SecureChannel_deleteMembersCleanup(UA_SecureChannel *channel);
UA_StatusCode UA_SecureChannel_generateNonce(UA_ByteString *nonce);
void UA_SecureChannel_attachSession(UA_SecureChannel *channel, UA_Session *session);
void UA_SecureChannel_detachSession(UA_SecureChannel *channel, UA_Session *session);
UA_Session * UA_SecureChannel_getSession(UA_SecureChannel *channel, UA_NodeId *token);
UA_StatusCode UA_SecureChannel_sendBinaryMessage(UA_SecureChannel *channel, UA_UInt32 requestId,
const void *content, const UA_DataType *contentType);
void UA_SecureChannel_revolveTokens(UA_SecureChannel *channel);
/*********************************** amalgamated original file "/home/wn/Sources/open62541-open62541-395ce48/src/server/ua_nodes.h" ***********************************/
/*
* Most APIs take and return UA_EditNode and UA_ConstNode. By looking up the
* nodeclass, nodes can be cast to their "true" class, i.e. UA_VariableNode,
* UA_ObjectNode, and so on.
*/
#define UA_STANDARD_NODEMEMBERS \
UA_NodeId nodeId; \
UA_NodeClass nodeClass; \
UA_QualifiedName browseName; \
UA_LocalizedText displayName; \
UA_LocalizedText description; \
UA_UInt32 writeMask; \
UA_UInt32 userWriteMask; \
size_t referencesSize; \
UA_ReferenceNode *references;
typedef struct {
UA_STANDARD_NODEMEMBERS
} UA_Node;
void UA_Node_deleteMembersAnyNodeClass(UA_Node *node);
UA_StatusCode UA_Node_copyAnyNodeClass(const UA_Node *src, UA_Node *dst);
/**************/
/* ObjectNode */
/**************/
typedef struct {
UA_STANDARD_NODEMEMBERS
UA_Byte eventNotifier;
void *instanceHandle;
} UA_ObjectNode;
/******************/
/* ObjectTypeNode */
/******************/
typedef struct {
UA_STANDARD_NODEMEMBERS
UA_Boolean isAbstract;
UA_ObjectLifecycleManagement lifecycleManagement;
} UA_ObjectTypeNode;
typedef enum {
UA_VALUESOURCE_VARIANT,
UA_VALUESOURCE_DATASOURCE
} UA_ValueSource;
/****************/
/* VariableNode */
/****************/
typedef struct {
UA_STANDARD_NODEMEMBERS
UA_Int32 valueRank; /**< n >= 1: the value is an array with the specified number of dimensions.
n = 0: the value is an array with one or more dimensions.
n = -1: the value is a scalar.
n = -2: the value can be a scalar or an array with any number of dimensions.
n = -3: the value can be a scalar or a one dimensional array. */
UA_ValueSource valueSource;
union {
struct {
UA_Variant value;
UA_ValueCallback callback;
} variant;
UA_DataSource dataSource;
} value;
/* <--- similar to variabletypenodes up to there--->*/
UA_Byte accessLevel;
UA_Byte userAccessLevel;
UA_Double minimumSamplingInterval;
UA_Boolean historizing;
} UA_VariableNode;
/********************/
/* VariableTypeNode */
/********************/
typedef struct {
UA_STANDARD_NODEMEMBERS
UA_Int32 valueRank;
UA_ValueSource valueSource;
union {
struct {
UA_Variant value;
UA_ValueCallback callback;
} variant;
UA_DataSource dataSource;
} value;
/* <--- similar to variablenodes up to there--->*/
UA_Boolean isAbstract;
} UA_VariableTypeNode;
/*********************/
/* ReferenceTypeNode */
/*********************/
typedef struct {
UA_STANDARD_NODEMEMBERS
UA_Boolean isAbstract;
UA_Boolean symmetric;
UA_LocalizedText inverseName;
} UA_ReferenceTypeNode;
/**************/
/* MethodNode */
/**************/
typedef struct {
UA_STANDARD_NODEMEMBERS
UA_Boolean executable;
UA_Boolean userExecutable;
void *methodHandle;
UA_MethodCallback attachedMethod;
} UA_MethodNode;
/************/
/* ViewNode */
/************/
typedef struct {
UA_STANDARD_NODEMEMBERS
UA_Byte eventNotifier;
/* <-- the same as objectnode until here --> */
UA_Boolean containsNoLoops;
} UA_ViewNode;
/****************/
/* DataTypeNode */
/****************/
typedef struct {
UA_STANDARD_NODEMEMBERS
UA_Boolean isAbstract;
} UA_DataTypeNode;
/*********************************** amalgamated original file "/home/wn/Sources/open62541-open62541-395ce48/src/ua_session.h" ***********************************/
#define MAXCONTINUATIONPOINTS 5
struct ContinuationPointEntry {
LIST_ENTRY(ContinuationPointEntry) pointers;
UA_ByteString identifier;
UA_BrowseDescription browseDescription;
UA_UInt32 continuationIndex;
UA_UInt32 maxReferences;
};
struct UA_Subscription;
typedef struct UA_Subscription UA_Subscription;
typedef struct UA_PublishResponseEntry {
SIMPLEQ_ENTRY(UA_PublishResponseEntry) listEntry;
UA_UInt32 requestId;
UA_PublishResponse response;
} UA_PublishResponseEntry;
struct UA_Session {
UA_ApplicationDescription clientDescription;
UA_Boolean activated;
UA_String sessionName;
UA_NodeId authenticationToken;
UA_NodeId sessionId;
UA_UInt32 maxRequestMessageSize;
UA_UInt32 maxResponseMessageSize;
UA_Double timeout; // [ms]
UA_DateTime validTill;
UA_SecureChannel *channel;
UA_UInt16 availableContinuationPoints;
LIST_HEAD(ContinuationPointList, ContinuationPointEntry) continuationPoints;
#ifdef UA_ENABLE_SUBSCRIPTIONS
UA_UInt32 lastSubscriptionID;
LIST_HEAD(UA_ListOfUASubscriptions, UA_Subscription) serverSubscriptions;
SIMPLEQ_HEAD(UA_ListOfQueuedPublishResponses, UA_PublishResponseEntry) responseQueue;
#endif
};
/* Local access to the services (for startup and maintenance) uses this Session
* with all possible access rights (Session ID: 1) */
extern UA_Session adminSession;
void UA_Session_init(UA_Session *session);
void UA_Session_deleteMembersCleanup(UA_Session *session, UA_Server *server);
/* If any activity on a session happens, the timeout is extended */
void UA_Session_updateLifetime(UA_Session *session);
#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);
UA_UInt32
UA_Session_getUniqueSubscriptionID(UA_Session *session);
#endif
/*********************************** amalgamated original file "/home/wn/Sources/open62541-open62541-395ce48/src/server/ua_subscription.h" ***********************************/
/*****************/
/* MonitoredItem */
/*****************/
typedef enum {
UA_MONITOREDITEMTYPE_CHANGENOTIFY = 1,
UA_MONITOREDITEMTYPE_STATUSNOTIFY = 2,
UA_MONITOREDITEMTYPE_EVENTNOTIFY = 4
} UA_MonitoredItemType;
typedef struct MonitoredItem_queuedValue {
TAILQ_ENTRY(MonitoredItem_queuedValue) listEntry;
UA_UInt32 clientHandle;
UA_DataValue value;
} MonitoredItem_queuedValue;
typedef struct UA_MonitoredItem {
LIST_ENTRY(UA_MonitoredItem) listEntry;
/* Settings */
UA_Subscription *subscription;
UA_UInt32 itemId;
UA_MonitoredItemType monitoredItemType;
UA_TimestampsToReturn timestampsToReturn;
UA_MonitoringMode monitoringMode;
UA_NodeId monitoredNodeId;
UA_UInt32 attributeID;
UA_UInt32 clientHandle;
UA_Double samplingInterval; // [ms]
UA_UInt32 currentQueueSize;
UA_UInt32 maxQueueSize;
UA_Boolean discardOldest;
UA_String indexRange;
// TODO: dataEncoding is hardcoded to UA binary
/* Sample Job */
UA_Guid sampleJobGuid;
UA_Boolean sampleJobIsRegistered;
/* Sample Queue */
UA_ByteString lastSampledValue;
TAILQ_HEAD(QueueOfQueueDataValues, MonitoredItem_queuedValue) queue;
} UA_MonitoredItem;
UA_MonitoredItem *UA_MonitoredItem_new(void);
void MonitoredItem_delete(UA_Server *server, UA_MonitoredItem *monitoredItem);
UA_StatusCode MonitoredItem_registerSampleJob(UA_Server *server, UA_MonitoredItem *mon);
UA_StatusCode MonitoredItem_unregisterSampleJob(UA_Server *server, UA_MonitoredItem *mon);
/****************/
/* Subscription */
/****************/
typedef struct UA_NotificationMessageEntry {
LIST_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;
struct UA_Subscription {
LIST_ENTRY(UA_Subscription) listEntry;
/* Settings */
UA_Session *session;
UA_UInt32 lifeTimeCount;
UA_UInt32 maxKeepAliveCount;
UA_Double publishingInterval; // [ms]
UA_UInt32 subscriptionID;
UA_UInt32 notificationsPerPublish;
UA_Boolean publishingEnabled;
UA_UInt32 priority;
UA_UInt32 sequenceNumber;
/* Runtime information */
UA_SubscriptionState state;
UA_UInt32 currentKeepAliveCount;
UA_UInt32 currentLifetimeCount;
/* Publish Job */
UA_Guid publishJobGuid;
UA_Boolean publishJobIsRegistered;
LIST_HEAD(UA_ListOfUAMonitoredItems, UA_MonitoredItem) MonitoredItems;
LIST_HEAD(UA_ListOfNotificationMessages, UA_NotificationMessageEntry) retransmissionQueue;
};
UA_Subscription *UA_Subscription_new(UA_Session *session, UA_UInt32 subscriptionID);
void UA_Subscription_deleteMembers(UA_Subscription *subscription, UA_Server *server);
UA_StatusCode Subscription_registerPublishJob(UA_Server *server, UA_Subscription *sub);
UA_StatusCode Subscription_unregisterPublishJob(UA_Server *server, UA_Subscription *sub);
UA_StatusCode
UA_Subscription_deleteMonitoredItem(UA_Server *server, UA_Subscription *sub,
UA_UInt32 monitoredItemID);
UA_MonitoredItem *
UA_Subscription_getMonitoredItem(UA_Subscription *sub, UA_UInt32 monitoredItemID);
void UA_Subscription_publishCallback(UA_Server *server, UA_Subscription *sub);
/*********************************** amalgamated original file "/home/wn/Sources/open62541-open62541-395ce48/src/server/ua_nodestore.h" ***********************************/
#ifdef __cplusplus
extern "C" {
#endif
/**
* Nodestore
* =========
* Stores nodes that can be indexed by their NodeId. Internally, it is based on
* a hash-map implementation. */
struct UA_NodeStore;
typedef struct UA_NodeStore UA_NodeStore;
/**
* Nodestore Lifecycle
* ------------------- */
/* Create a new nodestore */
UA_NodeStore * UA_NodeStore_new(void);
/* Delete the nodestore and all nodes in it. Do not call from a read-side
critical section (multithreading). */
void UA_NodeStore_delete(UA_NodeStore *ns);
/**
* Node Lifecycle
* ---------------
*
* The following definitions are used to create empty nodes of the different
* node types. The memory is managed by the nodestore. Therefore, the node has
* to be removed via a special deleteNode function. (If the new node is not
* added to the nodestore.) */
/* Create an editable node of the given NodeClass. */
UA_Node * UA_NodeStore_newNode(UA_NodeClass nodeClass);
#define UA_NodeStore_newObjectNode() (UA_ObjectNode*)UA_NodeStore_newNode(UA_NODECLASS_OBJECT)
#define UA_NodeStore_newVariableNode() (UA_VariableNode*)UA_NodeStore_newNode(UA_NODECLASS_VARIABLE)
#define UA_NodeStore_newMethodNode() (UA_MethodNode*)UA_NodeStore_newNode(UA_NODECLASS_METHOD)
#define UA_NodeStore_newObjectTypeNode() (UA_ObjectTypeNode*)UA_NodeStore_newNode(UA_NODECLASS_OBJECTTYPE)
#define UA_NodeStore_newVariableTypeNode() (UA_VariableTypeNode*)UA_NodeStore_newNode(UA_NODECLASS_VARIABLETYPE)
#define UA_NodeStore_newReferenceTypeNode() (UA_ReferenceTypeNode*)UA_NodeStore_newNode(UA_NODECLASS_REFERENCETYPE)
#define UA_NodeStore_newDataTypeNode() (UA_DataTypeNode*)UA_NodeStore_newNode(UA_NODECLASS_DATATYPE)
#define UA_NodeStore_newViewNode() (UA_ViewNode*)UA_NodeStore_newNode(UA_NODECLASS_VIEW)
/* Delete an editable node. */
void UA_NodeStore_deleteNode(UA_Node *node);
/**
* Insert / Get / Replace / Remove
* ------------------------------- */
/* Inserts a new node into the nodestore. If the nodeid is zero, then a fresh
* numeric nodeid from namespace 1 is assigned. If insertion fails, the node is
* deleted. */
UA_StatusCode UA_NodeStore_insert(UA_NodeStore *ns, UA_Node *node);
/* The returned node is immutable. */
const UA_Node * UA_NodeStore_get(UA_NodeStore *ns, const UA_NodeId *nodeid);
/* Returns an editable copy of a node (needs to be deleted with the deleteNode
function or inserted / replaced into the nodestore). */
UA_Node * UA_NodeStore_getCopy(UA_NodeStore *ns, const UA_NodeId *nodeid);
/* To replace a node, get an editable copy of the node, edit and replace with
* this function. If the node was already replaced since the copy was made,
* UA_STATUSCODE_BADINTERNALERROR is returned. If the nodeid is not found,
* UA_STATUSCODE_BADNODEIDUNKNOWN is returned. In both error cases, the editable
* node is deleted. */
UA_StatusCode UA_NodeStore_replace(UA_NodeStore *ns, UA_Node *node);
/* Remove a node in the nodestore. */
UA_StatusCode UA_NodeStore_remove(UA_NodeStore *ns, const UA_NodeId *nodeid);
/**
* Iteration
* ---------
* The following definitions are used to call a callback for every node in the
* nodestore. */
typedef void (*UA_NodeStore_nodeVisitor)(const UA_Node *node);
void UA_NodeStore_iterate(UA_NodeStore *ns, UA_NodeStore_nodeVisitor visitor);
#ifdef __cplusplus
} // extern "C"
#endif
/*********************************** amalgamated original file "/home/wn/Sources/open62541-open62541-395ce48/src/server/ua_session_manager.h" ***********************************/
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 maxSessionCount;
UA_UInt32 lastSessionId;
UA_UInt32 currentSessionCount;
UA_UInt32 maxSessionLifeTime; // time in [ms]
UA_Server *server;
} UA_SessionManager;
UA_StatusCode
UA_SessionManager_init(UA_SessionManager *sessionManager, UA_UInt32 maxSessionCount,
UA_UInt32 maxSessionLifeTime, UA_UInt32 startSessionId, UA_Server *server);
void UA_SessionManager_deleteMembers(UA_SessionManager *sessionManager);
void UA_SessionManager_cleanupTimedOut(UA_SessionManager *sessionManager, UA_DateTime now);
UA_StatusCode
UA_SessionManager_createSession(UA_SessionManager *sessionManager, UA_SecureChannel *channel,
const UA_CreateSessionRequest *request, UA_Session **session);
UA_StatusCode
UA_SessionManager_removeSession(UA_SessionManager *sessionManager, const UA_NodeId *token);
UA_Session *
UA_SessionManager_getSession(UA_SessionManager *sessionManager, const UA_NodeId *token);
/*********************************** amalgamated original file "/home/wn/Sources/open62541-open62541-395ce48/src/server/ua_securechannel_manager.h" ***********************************/
typedef struct channel_list_entry {
UA_SecureChannel channel;
LIST_ENTRY(channel_list_entry) pointers;
} channel_list_entry;
typedef struct UA_SecureChannelManager {
LIST_HEAD(channel_list, channel_list_entry) channels; // doubly-linked list of channels
size_t maxChannelCount;
size_t currentChannelCount;
UA_UInt32 maxChannelLifetime;
UA_MessageSecurityMode securityMode;
UA_DateTime channelLifeTime;
UA_UInt32 lastChannelId;
UA_UInt32 lastTokenId;
UA_Server *server;
} UA_SecureChannelManager;
UA_StatusCode
UA_SecureChannelManager_init(UA_SecureChannelManager *cm, size_t maxChannelCount,
UA_UInt32 tokenLifetime, UA_UInt32 startChannelId,
UA_UInt32 startTokenId, UA_Server *server);
void UA_SecureChannelManager_deleteMembers(UA_SecureChannelManager *cm);
void UA_SecureChannelManager_cleanupTimedOut(UA_SecureChannelManager *cm, UA_DateTime now);
UA_StatusCode
UA_SecureChannelManager_open(UA_SecureChannelManager *cm, UA_Connection *conn,
const UA_OpenSecureChannelRequest *request,
UA_OpenSecureChannelResponse *response);
UA_StatusCode
UA_SecureChannelManager_renew(UA_SecureChannelManager *cm, UA_Connection *conn,
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);
/*********************************** amalgamated original file "/home/wn/Sources/open62541-open62541-395ce48/src/server/ua_server_internal.h" ***********************************/
#define ANONYMOUS_POLICY "open62541-anonymous-policy"
#define USERNAME_POLICY "open62541-username-policy"
#ifdef UA_ENABLE_EXTERNAL_NAMESPACES
/** Mapping of namespace-id and url to an external nodestore. For namespaces
that have no mapping defined, the internal nodestore is used by default. */
typedef struct UA_ExternalNamespace {
UA_UInt16 index;
UA_String url;
UA_ExternalNodeStore externalNodeStore;
} UA_ExternalNamespace;
#endif
#ifdef UA_ENABLE_MULTITHREADING
typedef struct {
UA_Server *server;
pthread_t thr;
UA_UInt32 counter;
volatile UA_Boolean running;
char padding[64 - sizeof(void*) - sizeof(pthread_t) -
sizeof(UA_UInt32) - sizeof(UA_Boolean)]; // separate cache lines
} UA_Worker;
#endif
struct UA_Server {
/* Meta */
UA_DateTime startTime;
size_t endpointDescriptionsSize;
UA_EndpointDescription *endpointDescriptions;
/* Security */
UA_SecureChannelManager secureChannelManager;
UA_SessionManager sessionManager;
/* Address Space */
UA_NodeStore *nodestore;
size_t namespacesSize;
UA_String *namespaces;
#ifdef UA_ENABLE_EXTERNAL_NAMESPACES
size_t externalNamespacesSize;
UA_ExternalNamespace *externalNamespaces;
#endif
/* Jobs with a repetition interval */
LIST_HEAD(RepeatedJobsList, RepeatedJobs) repeatedJobs;
#ifdef UA_ENABLE_MULTITHREADING
/* Dispatch queue head for the worker threads (the tail should not be in the same cache line) */
struct cds_wfcq_head dispatchQueue_head;
UA_Worker *workers; /* there are nThread workers in a running server */
struct cds_lfs_stack mainLoopJobs; /* Work that shall be executed only in the main loop and not
by worker threads */
struct DelayedJobs *delayedJobs;
pthread_cond_t dispatchQueue_condition; /* so the workers don't spin if the queue is empty */
struct cds_wfcq_tail dispatchQueue_tail; /* Dispatch queue tail for the worker threads */
#endif
/* Config is the last element so that MSVC allows the usernamePasswordLogins
field with zero-sized array */
UA_ServerConfig config;
};
typedef UA_StatusCode (*UA_EditNodeCallback)(UA_Server*, UA_Session*, UA_Node*, const void*);
/* Calls callback on the node. In the multithreaded case, the node is copied before and replaced in
the nodestore. */
UA_StatusCode UA_Server_editNode(UA_Server *server, UA_Session *session, const UA_NodeId *nodeId,
UA_EditNodeCallback callback, const void *data);
void UA_Server_processBinaryMessage(UA_Server *server, UA_Connection *connection, const UA_ByteString *msg);
UA_StatusCode UA_Server_delayedCallback(UA_Server *server, UA_ServerCallback callback, void *data);
UA_StatusCode UA_Server_delayedFree(UA_Server *server, void *data);
void UA_Server_deleteAllRepeatedJobs(UA_Server *server);
#ifdef UA_BUILD_UNIT_TESTS
UA_StatusCode parse_numericrange(const UA_String *str, UA_NumericRange *range);
#endif
/*********************************** amalgamated original file "/home/wn/Sources/open62541-open62541-395ce48/src/server/ua_services.h" ***********************************/
#ifdef __cplusplus
extern "C" {
#endif
/**
* .. _services:
*
* Services
* ========
* The services defined in the OPC UA standard. */
/* Most services take as input the server, the current session and pointers to
the request and response. The possible error codes are returned as part of
the response. */
typedef void (*UA_Service)(UA_Server*, UA_Session*, const void*, void*);
/**
* 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. */
void Service_FindServers(UA_Server *server, UA_Session *session,
const UA_FindServersRequest *request,
UA_FindServersResponse *response);
/* 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);
/* Not Implemented: Service_RegisterServer */
/**
* 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. */
/* 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_Connection *connection,
const UA_OpenSecureChannelRequest *request,
UA_OpenSecureChannelResponse *response);
/** Used to terminate a SecureChannel. */
void Service_CloseSecureChannel(UA_Server *server, UA_UInt32 channelId);
/**
* Session Service Set
* -------------------
* This Service Set defines Services for an application layer connection
* establishment in the context of a Session. */
/* 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_Session *session,
const UA_CreateSessionRequest *request,
UA_CreateSessionResponse *response);
/* 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_Session *session,
const UA_ActivateSessionRequest *request,
UA_ActivateSessionResponse *response);
/* Used to terminate a Session. */
void Service_CloseSession(UA_Server *server, UA_Session *session,
const UA_CloseSessionRequest *request,
UA_CloseSessionResponse *response);
/* Not Implemented: Service_Cancel */
/**
* 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. */
/* 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);
void Service_AddNodes_single(UA_Server *server, UA_Session *session,
const UA_AddNodesItem *item, UA_AddNodesResult *result,
UA_InstantiationCallback *instantiationCallback);
/* Add an existing node. The node is assumed to be "finished", i.e. no
* instantiation from inheritance is necessary */
void Service_AddNodes_existing(UA_Server *server, UA_Session *session, UA_Node *node,
const UA_NodeId *parentNodeId, const UA_NodeId *referenceTypeId,
UA_AddNodesResult *result);
/* 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);
UA_StatusCode Service_AddReferences_single(UA_Server *server, UA_Session *session,
const UA_AddReferencesItem *item);
/* 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);
UA_StatusCode Service_DeleteNodes_single(UA_Server *server, UA_Session *session,
const UA_NodeId *nodeId,
UA_Boolean 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);
UA_StatusCode Service_DeleteReferences_single(UA_Server *server, UA_Session *session,
const UA_DeleteReferencesItem *item);
/**
* 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. */
/* 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);
void Service_Browse_single(UA_Server *server, UA_Session *session,
struct ContinuationPointEntry *cp, const UA_BrowseDescription *descr,
UA_UInt32 maxrefs, UA_BrowseResult *result);
/* 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);
void UA_Server_browseNext_single(UA_Server *server, UA_Session *session,
UA_Boolean releaseContinuationPoint,
const UA_ByteString *continuationPoint,
UA_BrowseResult *result);
/* 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);
void Service_TranslateBrowsePathsToNodeIds_single(UA_Server *server, UA_Session *session,
const UA_BrowsePath *path,
UA_BrowsePathResult *result);
/* 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);
/* 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. */
/* Not Implemented: Service_QueryFirst */
/* Not Impelemented: Service_QueryNext */
/**
* Attribute Service Set
* ---------------------
* This Service Set provides Services to access Attributes that are part of
* Nodes. */
/* Used to read one or more Attributes of one or more 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. */
void Service_Read(UA_Server *server, UA_Session *session,
const UA_ReadRequest *request,
UA_ReadResponse *response);
void Service_Read_single(UA_Server *server, UA_Session *session,
UA_TimestampsToReturn timestamps,
const UA_ReadValueId *id, UA_DataValue *v);
/* Used to write one or more Attributes of one or more 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);
UA_StatusCode Service_Write_single(UA_Server *server, UA_Session *session,
const UA_WriteValue *wvalue);
/* Not Implemented: Service_HistoryRead */
/* Not Implemented: Service_HistoryUpdate */
/**
* Method Service Set
* ------------------
* The Method Service Set defines the means to invoke methods. A method shall be
* a component of an Object. */
#ifdef UA_ENABLE_METHODCALLS
/* Used to call (invoke) a list of 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);
void Service_Call_single(UA_Server *server, UA_Session *session,
const UA_CallMethodRequest *request,
UA_CallMethodResult *result);
#endif
/**
* 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. */
#ifdef UA_ENABLE_SUBSCRIPTIONS
/* 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);
/* 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);
void Service_ModifyMonitoredItems(UA_Server *server, UA_Session *session,
const UA_ModifyMonitoredItemsRequest *request,
UA_ModifyMonitoredItemsResponse *response);
/* Not Implemented: Service_SetMonitoringMode */
/* Not Implemented: Service_SetTriggering */
#endif
/**
* Subscription Service Set
* ------------------------
* Subscriptions are used to report Notifications to the Client. */
#ifdef UA_ENABLE_SUBSCRIPTIONS
/* 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);
/* Used to modify a Subscription. */
void Service_ModifySubscription(UA_Server *server, UA_Session *session,
const UA_ModifySubscriptionRequest *request,
UA_ModifySubscriptionResponse *response);
/* 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);
/* 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);
/* 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);
/* 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);
/* Not Implemented: Service_TransferSubscription */
#endif
#ifdef __cplusplus
} // extern "C"
#endif
/*********************************** amalgamated original file "/home/wn/Sources/open62541-open62541-395ce48/src/client/ua_client_internal.h" ***********************************/
/**************************/
/* Subscriptions Handling */
/**************************/
#ifdef UA_ENABLE_SUBSCRIPTIONS
typedef struct UA_Client_NotificationsAckNumber_s {
UA_SubscriptionAcknowledgement subAck;
LIST_ENTRY(UA_Client_NotificationsAckNumber_s) listEntry;
} UA_Client_NotificationsAckNumber;
typedef struct UA_Client_MonitoredItem_s {
UA_UInt32 MonitoredItemId;
UA_UInt32 MonitoringMode;
UA_NodeId monitoredNodeId;
UA_UInt32 AttributeID;
UA_UInt32 ClientHandle;
UA_Double SamplingInterval;
UA_UInt32 QueueSize;
UA_Boolean DiscardOldest;
void (*handler)(UA_UInt32 monId, UA_DataValue *value, void *context);
void *handlerContext;
LIST_ENTRY(UA_Client_MonitoredItem_s) listEntry;
} UA_Client_MonitoredItem;
typedef struct UA_Client_Subscription_s {
UA_UInt32 LifeTime;
UA_UInt32 KeepAliveCount;
UA_Double PublishingInterval;
UA_UInt32 SubscriptionID;
UA_UInt32 NotificationsPerPublish;
UA_UInt32 Priority;
LIST_ENTRY(UA_Client_Subscription_s) listEntry;
LIST_HEAD(UA_ListOfClientMonitoredItems, UA_Client_MonitoredItem_s) MonitoredItems;
} UA_Client_Subscription;
#endif
/**********/
/* Client */
/**********/
typedef enum {
UA_CLIENTAUTHENTICATION_NONE,
UA_CLIENTAUTHENTICATION_USERNAME
} UA_Client_Authentication;
struct UA_Client {
/* State */
UA_ClientState state;
/* Connection */
UA_Connection connection;
UA_SecureChannel channel;
UA_String endpointUrl;
UA_UInt32 requestId;
/* Authentication */
UA_Client_Authentication authenticationMethod;
UA_String username;
UA_String password;
/* Session */
UA_UserTokenPolicy token;
UA_NodeId sessionId;
UA_NodeId authenticationToken;
UA_UInt32 requestHandle;
#ifdef UA_ENABLE_SUBSCRIPTIONS
UA_UInt32 monitoredItemHandles;
LIST_HEAD(UA_ListOfUnacknowledgedNotificationNumbers, UA_Client_NotificationsAckNumber_s) pendingNotificationsAcks;
LIST_HEAD(UA_ListOfClientSubscriptionItems, UA_Client_Subscription_s) subscriptions;
#endif
/* Config */
UA_ClientConfig config;
UA_DateTime scRenewAt;
};
/*********************************** amalgamated original file "/home/wn/Sources/open62541-open62541-395ce48/src/server/ua_nodestore_hash.inc" ***********************************/
typedef UA_UInt32 hash_t;
static hash_t mod(hash_t h, hash_t size) { return h % size; }
static hash_t mod2(hash_t h, hash_t size) { return 1 + (h % (size - 2)); }
/* Based on Murmur-Hash 3 by Austin Appleby (public domain, freely usable) */
static hash_t hash_array(const UA_Byte *data, UA_UInt32 len, UA_UInt32 seed) {
if(data == NULL)
return 0;
const int32_t nblocks = (int32_t)(len / 4);
const uint32_t *blocks;
static const uint32_t c1 = 0xcc9e2d51;
static const uint32_t c2 = 0x1b873593;
static const uint32_t r1 = 15;
static const uint32_t r2 = 13;
static const uint32_t m = 5;
static const uint32_t n = 0xe6546b64;
hash_t hash = seed;
/* Somce compilers emit a warning when casting from a byte array to ints. */
#if ((__GNUC__ == 4 && __GNUC_MINOR__ >= 6) || __GNUC__ > 4 || defined(__clang__))
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wcast-align"
#endif
blocks = (const uint32_t *)data;
#if ((__GNUC__ == 4 && __GNUC_MINOR__ >= 6) || __GNUC__ > 4 || defined(__clang__))
#pragma GCC diagnostic pop
#endif
for(int32_t i = 0;i < nblocks;i++) {
uint32_t k = blocks[i];
k *= c1;
k = (k << r1) | (k >> (32 - r1));
k *= c2;
hash ^= k;
hash = ((hash << r2) | (hash >> (32 - r2))) * m + n;
}
const uint8_t *tail = (const uint8_t *)(data + nblocks * 4);
uint32_t k1 = 0;
switch(len & 3) {
case 3:
k1 ^= (uint32_t)(tail[2] << 16);
case 2:
k1 ^= (uint32_t)(tail[1] << 8);
case 1:
k1 ^= tail[0];
k1 *= c1;
k1 = (k1 << r1) | (k1 >> (32 - r1));
k1 *= c2;
hash ^= k1;
}
hash ^= len;
hash ^= (hash >> 16);
hash *= 0x85ebca6b;
hash ^= (hash >> 13);
hash *= 0xc2b2ae35;
hash ^= (hash >> 16);
return hash;
}
static hash_t hash(const UA_NodeId *n) {
switch(n->identifierType) {
case UA_NODEIDTYPE_NUMERIC:
/* Knuth's multiplicative hashing */
return (hash_t)((n->identifier.numeric + n->namespaceIndex) * 2654435761); // mod(2^32) is implicit
case UA_NODEIDTYPE_STRING:
return hash_array(n->identifier.string.data, (UA_UInt32)n->identifier.string.length,
n->namespaceIndex);
case UA_NODEIDTYPE_GUID:
return hash_array((const UA_Byte*)&(n->identifier.guid), sizeof(UA_Guid), n->namespaceIndex);
case UA_NODEIDTYPE_BYTESTRING:
return hash_array((const UA_Byte*)n->identifier.byteString.data,
(UA_UInt32)n->identifier.byteString.length, n->namespaceIndex);
default:
UA_assert(false);
return 0;
}
}
/*********************************** amalgamated original file "/home/wn/Sources/open62541-open62541-395ce48/src/ua_types.c" ***********************************/
/* static variables */
UA_EXPORT const UA_String UA_STRING_NULL = {.length = 0, .data = NULL };
UA_EXPORT const UA_ByteString UA_BYTESTRING_NULL = {.length = 0, .data = NULL };
UA_EXPORT const UA_NodeId UA_NODEID_NULL = {0, UA_NODEIDTYPE_NUMERIC, {0}};
UA_EXPORT const UA_ExpandedNodeId UA_EXPANDEDNODEID_NULL = {
.nodeId = { .namespaceIndex = 0, .identifierType = UA_NODEIDTYPE_NUMERIC, .identifier.numeric = 0 },
.namespaceUri = {.length = 0, .data = NULL}, .serverIndex = 0 };
/***************************/
/* Random Number Generator */
/***************************/
static UA_THREAD_LOCAL pcg32_random_t UA_rng = PCG32_INITIALIZER;
UA_EXPORT void UA_random_seed(UA_UInt64 seed) {
pcg32_srandom_r(&UA_rng, seed, (uint64_t)UA_DateTime_now());
}
/*****************/
/* Builtin Types */
/*****************/
UA_EXPORT UA_UInt32 UA_UInt32_random(void) {
return (UA_UInt32)pcg32_random_r(&UA_rng);
}
UA_String UA_String_fromChars(char const src[]) {
UA_String str = UA_STRING_NULL;
size_t length = strlen(src);
if(length > 0) {
str.data = UA_malloc(length);
if(!str.data)
return str;
} else
str.data = UA_EMPTY_ARRAY_SENTINEL;
memcpy(str.data, src, length);
str.length = length;
return str;
}
UA_Boolean UA_String_equal(const UA_String *string1, const UA_String *string2) {
if(string1->length != string2->length)
return false;
UA_Int32 is = memcmp((char const*)string1->data, (char const*)string2->data, string1->length);
return (is == 0) ? true : false;
}
/* DateTime */
UA_DateTime UA_DateTime_now(void) {
#ifdef _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_SEC_TO_DATETIME) + (tv.tv_usec * UA_USEC_TO_DATETIME) + UA_DATETIME_UNIX_EPOCH;
#endif
}
UA_DateTime UA_DateTime_nowMonotonic(void) {
#ifdef _WIN32
LARGE_INTEGER freq, ticks;
QueryPerformanceFrequency(&freq);
QueryPerformanceCounter(&ticks);
UA_Double ticks2dt = UA_SEC_TO_DATETIME;
ticks2dt /= 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_SEC_TO_DATETIME) + (mts.tv_nsec / 100);
#else
struct timespec ts;
#ifdef __CYGWIN__
clock_gettime(CLOCK_MONOTONIC, &ts);
#else
clock_gettime(CLOCK_MONOTONIC_RAW, &ts);
#endif
return (ts.tv_sec * UA_SEC_TO_DATETIME) + (ts.tv_nsec / 100);
#endif
}
UA_DateTimeStruct UA_DateTime_toStruct(UA_DateTime t) {
/* Calculating the the milli-, micro- and nanoseconds */
UA_DateTimeStruct dateTimeStruct;
dateTimeStruct.nanoSec = (UA_UInt16)((t % 10) * 100);
dateTimeStruct.microSec = (UA_UInt16)((t % 10000) / 10);
dateTimeStruct.milliSec = (UA_UInt16)((t % 10000000) / 10000);
/* Calculating the unix time with #include <time.h> */
time_t secSinceUnixEpoch = (time_t)((t - UA_DATETIME_UNIX_EPOCH) / UA_SEC_TO_DATETIME);
struct tm ts;
memset(&ts, 0, sizeof(struct tm));
__secs_to_tm(secSinceUnixEpoch, &ts);
dateTimeStruct.sec = (UA_UInt16)ts.tm_sec;
dateTimeStruct.min = (UA_UInt16)ts.tm_min;
dateTimeStruct.hour = (UA_UInt16)ts.tm_hour;
dateTimeStruct.day = (UA_UInt16)ts.tm_mday;
dateTimeStruct.month = (UA_UInt16)(ts.tm_mon + 1);
dateTimeStruct.year = (UA_UInt16)(ts.tm_year + 1900);
return dateTimeStruct;
}
static void printNumber(UA_UInt16 n, UA_Byte *pos, size_t digits) {
for(size_t i = digits; i > 0; i--) {
pos[i-1] = (UA_Byte)((n % 10) + '0');
n = n / 10;
}
}
UA_String UA_DateTime_toString(UA_DateTime t) {
UA_String str = UA_STRING_NULL;
// length of the string is 31 (plus \0 at the end)
if(!(str.data = UA_malloc(32)))
return str;
str.length = 31;
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 = (UA_UInt32)pcg32_random_r(&UA_rng);
UA_UInt32 r = (UA_UInt32)pcg32_random_r(&UA_rng);
result.data2 = (UA_UInt16) r;
result.data3 = (UA_UInt16) (r >> 16);
r = (UA_UInt32)pcg32_random_r(&UA_rng);
result.data4[0] = (UA_Byte)r;
result.data4[1] = (UA_Byte)(r >> 4);
result.data4[2] = (UA_Byte)(r >> 8);
result.data4[3] = (UA_Byte)(r >> 12);
r = (UA_UInt32)pcg32_random_r(&UA_rng);
result.data4[4] = (UA_Byte)r;
result.data4[5] = (UA_Byte)(r >> 4);
result.data4[6] = (UA_Byte)(r >> 8);
result.data4[7] = (UA_Byte)(r >> 12);
return result;
}
/* ByteString */
UA_StatusCode UA_ByteString_allocBuffer(UA_ByteString *bs, size_t length) {
if(!(bs->data = UA_malloc(length)))
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:
UA_free((void*)((uintptr_t)p->identifier.byteString.data & ~(uintptr_t)UA_EMPTY_ARRAY_SENTINEL));
p->identifier.byteString = UA_BYTESTRING_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;
if(retval != UA_STATUSCODE_GOOD)
NodeId_deleteMembers(dst, NULL);
return retval;
}
UA_Boolean UA_NodeId_equal(const UA_NodeId *n1, const UA_NodeId *n2) {
if(n1->namespaceIndex != n2->namespaceIndex || n1->identifierType!=n2->identifierType)
return false;
switch(n1->identifierType) {
case UA_NODEIDTYPE_NUMERIC:
if(n1->identifier.numeric == n2->identifier.numeric)
return true;
else
return false;
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;
}
/* ExpandedNodeId */
static void ExpandedNodeId_deleteMembers(UA_ExpandedNodeId *p, const UA_DataType *_) {
NodeId_deleteMembers(&p->nodeId, _);
UA_String_deleteMembers(&p->namespaceUri);
}
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;
if(retval != UA_STATUSCODE_GOOD)
ExpandedNodeId_deleteMembers(dst, NULL);
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);
UA_free((void*)((uintptr_t)p->content.encoded.body.data & ~(uintptr_t)UA_EMPTY_ARRAY_SENTINEL));
p->content.encoded.body = UA_BYTESTRING_NULL;
break;
case UA_EXTENSIONOBJECT_DECODED:
if(!p->content.decoded.data)
break;
UA_delete(p->content.decoded.data, p->content.decoded.type);
p->content.decoded.data = NULL;
p->content.decoded.type = NULL;
break;
case UA_EXTENSIONOBJECT_DECODED_NODELETE:
p->content.decoded.type = NULL;
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->data > UA_EMPTY_ARRAY_SENTINEL) {
if(p->arrayLength == 0)
p->arrayLength = 1;
UA_Array_delete(p->data, p->arrayLength, p->type);
p->data = NULL;
p->arrayLength = 0;
}
if(p->arrayDimensions) {
UA_Array_delete(p->arrayDimensions, p->arrayDimensionsSize, &UA_TYPES[UA_TYPES_INT32]);
p->arrayDimensions = NULL;
p->arrayDimensionsSize = 0;
}
}
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)
dst->arrayDimensionsSize = src->arrayDimensionsSize;
else
Variant_deletemembers(dst, NULL);
}
return retval;
}
/**
* 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
processRangeDefinition(const UA_Variant *v, const UA_NumericRange range, size_t *total,
size_t *block, size_t *stride, size_t *first) {
/* Test the integrity of the source variant dimensions */
size_t dims_count = 1;
UA_UInt32 elements = 1;
#if(MAX_SIZE > 0xffffffff) /* 64bit only */
if(v->arrayLength > UA_UINT32_MAX)
return UA_STATUSCODE_BADINTERNALERROR;
#endif
UA_UInt32 arrayLength = (UA_UInt32)v->arrayLength;
const UA_UInt32 *dims = &arrayLength;
if(v->arrayDimensionsSize > 0) {
dims_count = v->arrayDimensionsSize;
dims = (UA_UInt32*)v->arrayDimensions;
for(size_t i = 0; i < dims_count; i++) {
/* dimensions can have negative size similar to array lengths */
if(v->arrayDimensions[i] < 0)
return UA_STATUSCODE_BADINDEXRANGEINVALID;
elements *= dims[i];
}
if(elements != v->arrayLength)
return UA_STATUSCODE_BADINTERNALERROR;
}
/* Test the integrity of the range */
size_t count = 1;
if(range.dimensionsSize != dims_count)
return UA_STATUSCODE_BADINDEXRANGEINVALID;
for(size_t i = 0; i < dims_count; i++) {
if(range.dimensions[i].min > range.dimensions[i].max)
return UA_STATUSCODE_BADINDEXRANGENODATA;
if(range.dimensions[i].max >= dims[i])
return UA_STATUSCODE_BADINDEXRANGEINVALID;
count *= (range.dimensions[i].max - range.dimensions[i].min) + 1;
}
/* Compute the stride length and the position of the first element */
size_t b = 1, s = elements, f = 0;
size_t running_dimssize = 1;
UA_Boolean found_contiguous = false;
for(size_t k = dims_count - 1; ; k--) {
if(!found_contiguous && (range.dimensions[k].min != 0 || range.dimensions[k].max + 1 != dims[k])) {
found_contiguous = true;
b = (range.dimensions[k].max - range.dimensions[k].min + 1) * running_dimssize;
s = dims[k] * running_dimssize;
}
f += running_dimssize * range.dimensions[k].min;
running_dimssize *= dims[k];
if(k == 0)
break;
}
*total = count;
*block = b;
*stride = s;
*first = f;
return UA_STATUSCODE_GOOD;
}
UA_StatusCode
UA_Variant_copyRange(const UA_Variant *src, UA_Variant *dst, const UA_NumericRange range) {
size_t count, block, stride, first;
UA_StatusCode retval = processRangeDefinition(src, range, &count, &block, &stride, &first);
if(retval != UA_STATUSCODE_GOOD)
return retval;
UA_Variant_init(dst);
size_t elem_size = src->type->memSize;
dst->data = UA_malloc(elem_size * count);
if(!dst->data)
return UA_STATUSCODE_BADOUTOFMEMORY;
/* Copy the range */
size_t block_count = count / block;
uintptr_t nextdst = (uintptr_t)dst->data;
uintptr_t nextsrc = (uintptr_t)src->data + (elem_size * first);
if(src->type->fixedSize) {
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 && retval == UA_STATUSCODE_GOOD; j++) {
retval = UA_copy((const void*)nextsrc, (void*)nextdst, src->type);
nextdst += elem_size;
nextsrc += elem_size;
}
nextsrc += (stride - block) * elem_size;
}
if(retval != UA_STATUSCODE_GOOD) {
size_t copied = ((nextdst - elem_size) - (uintptr_t)dst->data) / elem_size;
UA_Array_delete(dst->data, copied, src->type);
dst->data = NULL;
return retval;
}
}
dst->arrayLength = count;
dst->type = src->type;
/* Copy the range dimensions */
if(src->arrayDimensionsSize > 0) {
dst->arrayDimensions = UA_Array_new(src->arrayDimensionsSize, &UA_TYPES[UA_TYPES_UINT32]);
if(!dst->arrayDimensions) {
Variant_deletemembers(dst, NULL);
return UA_STATUSCODE_BADOUTOFMEMORY;
}
dst->arrayDimensionsSize = src->arrayDimensionsSize;
for(size_t k = 0; k < src->arrayDimensionsSize; k++)
dst->arrayDimensions[k] = (UA_Int32)(range.dimensions[k].max - range.dimensions[k].min + 1);
}
return UA_STATUSCODE_GOOD;
}
UA_StatusCode
UA_Variant_setRange(UA_Variant *v, void * UA_RESTRICT array, size_t arraySize, const UA_NumericRange range) {
size_t count, block, stride, first;
UA_StatusCode retval = processRangeDefinition(v, range, &count, &block, &stride, &first);
if(retval != UA_STATUSCODE_GOOD)
return retval;
if(count != arraySize)
return UA_STATUSCODE_BADINDEXRANGEINVALID;
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;
for(size_t i = 0; i < block_count; i++) {
if(!v->type->fixedSize) {
for(size_t j = 0; j < block; j++) {
UA_deleteMembers((void*)nextdst, v->type);
nextdst += elem_size;
}
nextdst -= block * elem_size;
}
memcpy((void*)nextdst, (void*)nextsrc, elem_size * block);
nextsrc += block * elem_size;
nextdst += stride * elem_size;
}
return UA_STATUSCODE_GOOD;
}
UA_StatusCode
UA_Variant_setRangeCopy(UA_Variant *v, const void *array, size_t arraySize, const UA_NumericRange range) {
size_t count, block, stride, first;
UA_StatusCode retval = processRangeDefinition(v, range, &count, &block, &stride, &first);
if(retval != UA_STATUSCODE_GOOD)
return retval;
if(count != arraySize)
return UA_STATUSCODE_BADINDEXRANGEINVALID;
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->fixedSize) {
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++) {
UA_deleteMembers((void*)nextdst, v->type);
retval |= UA_copy((void*)nextsrc, (void*)nextdst, v->type);
nextdst += elem_size;
nextsrc += elem_size;
}
nextdst += (stride - block) * elem_size;
}
}
return retval;
}
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 *new = UA_malloc(type->memSize);
if(!new)
return UA_STATUSCODE_BADOUTOFMEMORY;
UA_StatusCode retval = UA_copy(p, new, type);
if(retval != UA_STATUSCODE_GOOD) {
UA_free(new);
//cppcheck-suppress memleak
return retval;
}
UA_Variant_setScalar(v, new, 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;
}
/* LocalizedText */
static void LocalizedText_deleteMembers(UA_LocalizedText *p, const UA_DataType *_) {
UA_String_deleteMembers(&p->locale);
UA_String_deleteMembers(&p->text);
}
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 *_) {
UA_String_deleteMembers(&p->additionalInfo);
if(p->hasInnerDiagnosticInfo && p->innerDiagnosticInfo) {
DiagnosticInfo_deleteMembers(p->innerDiagnosticInfo, NULL);
UA_free(p->innerDiagnosticInfo);
p->innerDiagnosticInfo = NULL;
p->hasInnerDiagnosticInfo = false;
}
}
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) {
if((dst->innerDiagnosticInfo = UA_malloc(sizeof(UA_DiagnosticInfo)))) {
retval |= DiagnosticInfo_copy(src->innerDiagnosticInfo, dst->innerDiagnosticInfo, NULL);
dst->hasInnerDiagnosticInfo = true;
} else {
dst->hasInnerDiagnosticInfo = false;
retval |= UA_STATUSCODE_BADOUTOFMEMORY;
}
}
if(retval != UA_STATUSCODE_GOOD)
DiagnosticInfo_deleteMembers(dst, NULL);
return retval;
}
/*******************/
/* Structure Types */
/*******************/
void * UA_new(const UA_DataType *type) {
void *p = UA_calloc(1, type->memSize);
return p;
}
static UA_StatusCode copyByte(const void *src, void *dst, const UA_DataType *_) {
memcpy(dst, src, sizeof(UA_Byte));
return UA_STATUSCODE_GOOD;
}
static UA_StatusCode copy2Byte(const void *src, void *dst, const UA_DataType *_) {
memcpy(dst, src, sizeof(UA_UInt16));
return UA_STATUSCODE_GOOD;
}
static UA_StatusCode copy4Byte(const void *src, void *dst, const UA_DataType *_) {
memcpy(dst, src, sizeof(UA_UInt32));
return UA_STATUSCODE_GOOD;
}
static UA_StatusCode copy8Byte(const void *src, void *dst, const UA_DataType *_) {
memcpy(dst, src, sizeof(UA_UInt64));
return UA_STATUSCODE_GOOD;
}
static UA_StatusCode copyFixedSize(const void *src, void *dst, const UA_DataType *type) {
memcpy(dst, src, type->memSize);
return UA_STATUSCODE_GOOD;
}
static UA_StatusCode copyNoInit(const void *src, void *dst, const UA_DataType *type);
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)copyNoInit, // String
(UA_copySignature)copy8Byte, // DateTime
(UA_copySignature)copyFixedSize, // Guid
(UA_copySignature)copyNoInit, // ByteString
(UA_copySignature)copyNoInit, // XmlElement
(UA_copySignature)NodeId_copy,
(UA_copySignature)ExpandedNodeId_copy,
(UA_copySignature)copy4Byte, // StatusCode
(UA_copySignature)copyNoInit, // QualifiedName
(UA_copySignature)LocalizedText_copy, // LocalizedText
(UA_copySignature)ExtensionObject_copy,
(UA_copySignature)DataValue_copy,
(UA_copySignature)Variant_copy,
(UA_copySignature)DiagnosticInfo_copy,
(UA_copySignature)copyNoInit // all others
};
static UA_StatusCode copyNoInit(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;
UA_Byte membersSize = type->membersSize;
for(size_t i = 0; i < membersSize; i++) {
const UA_DataTypeMember *member = &type->members[i];
const UA_DataType *typelists[2] = { UA_TYPES, &type[-type->typeIndex] };
const UA_DataType *memberType = &typelists[!member->namespaceZero][member->memberTypeIndex];
if(!member->isArray) {
ptrs += member->padding;
ptrd += member->padding;
size_t fi = memberType->builtin ? memberType->typeIndex : UA_BUILTIN_TYPES_COUNT;
retval |= copyJumpTable[fi]((const void*)ptrs, (void*)ptrd, memberType);
ptrs += memberType->memSize;
ptrd += memberType->memSize;
} else {
ptrs += member->padding;
ptrd += member->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, memberType);
*dst_size = size;
if(retval != UA_STATUSCODE_GOOD)
*dst_size = 0;
ptrs += sizeof(void*);
ptrd += sizeof(void*);
}
}
if(retval != UA_STATUSCODE_GOOD)
UA_deleteMembers(dst, type);
return retval;
}
UA_StatusCode UA_copy(const void *src, void *dst, const UA_DataType *type) {
memset(dst, 0, type->memSize);
return copyNoInit(src, dst, type);
}
typedef void (*UA_deleteMembersSignature)(void *p, const UA_DataType *type);
static void nopDeleteMembers(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)UA_deleteMembers, // String
(UA_deleteMembersSignature)nopDeleteMembers, // DateTime
(UA_deleteMembersSignature)nopDeleteMembers, // Guid
(UA_deleteMembersSignature)UA_deleteMembers, // ByteString
(UA_deleteMembersSignature)UA_deleteMembers, // XmlElement
(UA_deleteMembersSignature)NodeId_deleteMembers,
(UA_deleteMembersSignature)ExpandedNodeId_deleteMembers, // ExpandedNodeId
(UA_deleteMembersSignature)nopDeleteMembers, // StatusCode
(UA_deleteMembersSignature)UA_deleteMembers, // QualifiedName
(UA_deleteMembersSignature)LocalizedText_deleteMembers, // LocalizedText
(UA_deleteMembersSignature)ExtensionObject_deleteMembers,
(UA_deleteMembersSignature)DataValue_deleteMembers,
(UA_deleteMembersSignature)Variant_deletemembers,
(UA_deleteMembersSignature)DiagnosticInfo_deleteMembers,
(UA_deleteMembersSignature)UA_deleteMembers,
};
void UA_deleteMembers(void *p, const UA_DataType *type) {
uintptr_t ptr = (uintptr_t)p;
UA_Byte membersSize = type->membersSize;
for(size_t i = 0; i < membersSize; i++) {
const UA_DataTypeMember *member = &type->members[i];
const UA_DataType *typelists[2] = { UA_TYPES, &type[-type->typeIndex] };
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;
deleteMembersJumpTable[fi]((void*)ptr, memberType);
ptr += memberType->memSize;
} else {
ptr += member->padding;
size_t length = *(size_t*)ptr;
*(size_t*)ptr = 0;
ptr += sizeof(size_t);
UA_Array_delete(*(void**)ptr, length, memberType);
*(void**)ptr = NULL;
ptr += sizeof(void*);
}
}
}
void UA_delete(void *p, const UA_DataType *type) {
UA_deleteMembers(p, type);
UA_free(p);
}
/******************/
/* Array Handling */
/******************/
void * UA_Array_new(size_t size, const UA_DataType *type) {
if(size == 0)
return UA_EMPTY_ARRAY_SENTINEL;
return UA_calloc(size, type->memSize);
}
UA_StatusCode
UA_Array_copy(const void *src, size_t src_size, void **dst, const UA_DataType *type) {
if(src_size == 0) {
if(src == NULL)
*dst = NULL;
else
*dst= UA_EMPTY_ARRAY_SENTINEL;
return UA_STATUSCODE_GOOD;
}
/* calloc, so we don't have to check retval in every iteration of copying */
*dst = UA_calloc(src_size, type->memSize);
if(!*dst)
return UA_STATUSCODE_BADOUTOFMEMORY;
if(type->fixedSize) {
memcpy(*dst, src, type->memSize * src_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 < src_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, src_size, type);
*dst = NULL;
}
return retval;
}
void UA_Array_delete(void *p, size_t size, const UA_DataType *type) {
if(!type->fixedSize) {
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));
}
/*********************************** amalgamated original file "/home/wn/Sources/open62541-open62541-395ce48/src/ua_types_encoding_binary.c" ***********************************/
/* We give pointers to the current position and the last position in the buffer
instead of a string with an offset. */
typedef UA_Byte * UA_RESTRICT * const bufpos;
typedef UA_Byte const * bufend;
/* Jumptables for de-/encoding and computing the buffer length */
typedef UA_StatusCode (*UA_encodeBinarySignature)(const void *UA_RESTRICT src, const UA_DataType *type, bufpos pos, bufend end);
static const UA_encodeBinarySignature encodeBinaryJumpTable[UA_BUILTIN_TYPES_COUNT + 1];
typedef UA_StatusCode (*UA_decodeBinarySignature)(bufpos pos, bufend end, void *UA_RESTRICT dst, const UA_DataType *type);
static const UA_decodeBinarySignature decodeBinaryJumpTable[UA_BUILTIN_TYPES_COUNT + 1];
typedef size_t (*UA_calcSizeBinarySignature)(const void *UA_RESTRICT p, const UA_DataType *contenttype);
static const UA_calcSizeBinarySignature calcSizeBinaryJumpTable[UA_BUILTIN_TYPES_COUNT + 1];
/* Thread-local buffers used for exchanging the buffer for chunking */
UA_THREAD_LOCAL UA_ByteString *encodeBuf; /* the original buffer */
UA_THREAD_LOCAL UA_exchangeEncodeBuffer exchangeBufferCallback;
UA_THREAD_LOCAL void *exchangeBufferCallbackHandle;
static UA_StatusCode exchangeBuffer(bufpos pos, bufend *end) {
if(!exchangeBufferCallback)
return UA_STATUSCODE_BADENCODINGERROR;
size_t offset = ((uintptr_t)*pos - (uintptr_t)encodeBuf->data) / sizeof(UA_Byte);
UA_StatusCode retval = exchangeBufferCallback(exchangeBufferCallbackHandle, encodeBuf, offset);
/* set pos and end in order to continue encoding */
*pos = encodeBuf->data;
*end = &encodeBuf->data[encodeBuf->length];
return retval;
}
/*****************/
/* Integer Types */
/*****************/
/* The following en/decoding functions are used only when the architecture isn't
little-endian. */
static void UA_encode16(const UA_UInt16 v, UA_Byte buf[2]) {
buf[0] = (UA_Byte)v; buf[1] = (UA_Byte)(v >> 8);
}
static void UA_decode16(const UA_Byte buf[2], UA_UInt16 *v) {
*v = (UA_UInt16)((UA_UInt16)buf[0] + (((UA_UInt16)buf[1]) << 8));
}
static void UA_encode32(const UA_UInt32 v, UA_Byte buf[4]) {
buf[0] = (UA_Byte)v; buf[1] = (UA_Byte)(v >> 8);
buf[2] = (UA_Byte)(v >> 16); buf[3] = (UA_Byte)(v >> 24);
}
static void UA_decode32(const UA_Byte buf[4], UA_UInt32 *v) {
*v = (UA_UInt32)((UA_UInt32)buf[0] + (((UA_UInt32)buf[1]) << 8) +
(((UA_UInt32)buf[2]) << 16) + (((UA_UInt32)buf[3]) << 24));
}
static void UA_encode64(const UA_UInt64 v, UA_Byte buf[8]) {
buf[0] = (UA_Byte)v; buf[1] = (UA_Byte)(v >> 8);
buf[2] = (UA_Byte)(v >> 16); buf[3] = (UA_Byte)(v >> 24);
buf[4] = (UA_Byte)(v >> 32); buf[5] = (UA_Byte)(v >> 40);
buf[6] = (UA_Byte)(v >> 48); buf[7] = (UA_Byte)(v >> 56);
}
static void UA_decode64(const UA_Byte buf[8], UA_UInt64 *v) {
*v = (UA_UInt64)((UA_UInt64)buf[0] + (((UA_UInt64)buf[1]) << 8) +
(((UA_UInt64)buf[2]) << 16) + (((UA_UInt64)buf[3]) << 24) +
(((UA_UInt64)buf[4]) << 32) + (((UA_UInt64)buf[5]) << 40) +
(((UA_UInt64)buf[6]) << 48) + (((UA_UInt64)buf[7]) << 56));
}
/* Boolean */
static UA_StatusCode
Boolean_encodeBinary(const UA_Boolean *src, const UA_DataType *_, bufpos pos, bufend end) {
if(*pos + sizeof(UA_Boolean) > end)
return UA_STATUSCODE_BADENCODINGERROR;
**pos = *(const UA_Byte*)src;
(*pos)++;
return UA_STATUSCODE_GOOD;
}
static UA_StatusCode
Boolean_decodeBinary(bufpos pos, bufend end, UA_Boolean *dst, const UA_DataType *_) {
if(*pos + sizeof(UA_Boolean) > end)
return UA_STATUSCODE_BADDECODINGERROR;
*dst = (**pos > 0) ? true : false;
(*pos)++;
return UA_STATUSCODE_GOOD;
}
/* Byte */
static UA_StatusCode
Byte_encodeBinary(const UA_Byte *src, const UA_DataType *_, bufpos pos, bufend end) {
if(*pos + sizeof(UA_Byte) > end)
return UA_STATUSCODE_BADENCODINGERROR;
**pos = *(const UA_Byte*)src;
(*pos)++;
return UA_STATUSCODE_GOOD;
}
static UA_StatusCode
Byte_decodeBinary(bufpos pos, bufend end, UA_Byte *dst, const UA_DataType *_) {
if(*pos + sizeof(UA_Byte) > end)
return UA_STATUSCODE_BADDECODINGERROR;
*dst = **pos;
(*pos)++;
return UA_STATUSCODE_GOOD;
}
/* UInt16 */
static UA_StatusCode
UInt16_encodeBinary(UA_UInt16 const *src, const UA_DataType *_, bufpos pos, bufend end) {
if(*pos + sizeof(UA_UInt16) > end)
return UA_STATUSCODE_BADENCODINGERROR;
#if UA_BINARY_OVERLAYABLE_INTEGER
memcpy(*pos, src, sizeof(UA_UInt16));
#else
UA_encode16(*src, *pos);
#endif
(*pos) += 2;
return UA_STATUSCODE_GOOD;
}
static UA_INLINE UA_StatusCode
Int16_encodeBinary(UA_Int16 const *src, const UA_DataType *_, bufpos pos, bufend end) {
return UInt16_encodeBinary((const UA_UInt16*)src, NULL, pos, end);
}
static UA_StatusCode
UInt16_decodeBinary(bufpos pos, bufend end, UA_UInt16 *dst, const UA_DataType *_) {
if(*pos + sizeof(UA_UInt16) > end)
return UA_STATUSCODE_BADDECODINGERROR;
#if UA_BINARY_OVERLAYABLE_INTEGER
memcpy(dst, *pos, sizeof(UA_UInt16));
#else
UA_decode16(*pos, dst);
#endif
(*pos) += 2;
return UA_STATUSCODE_GOOD;
}
static UA_INLINE UA_StatusCode
Int16_decodeBinary(bufpos pos, bufend end, UA_Int16 *dst) {
return UInt16_decodeBinary(pos, end, (UA_UInt16*)dst, NULL);
}
/* UInt32 */
static UA_StatusCode
UInt32_encodeBinary(UA_UInt32 const *src, const UA_DataType *_, bufpos pos, bufend end) {
if(*pos + sizeof(UA_UInt32) > end)
return UA_STATUSCODE_BADENCODINGERROR;
#if UA_BINARY_OVERLAYABLE_INTEGER
memcpy(*pos, src, sizeof(UA_UInt32));
#else
UA_encode32(*src, *pos);
#endif
(*pos) += 4;
return UA_STATUSCODE_GOOD;
}
static UA_INLINE UA_StatusCode
Int32_encodeBinary(UA_Int32 const *src, bufpos pos, bufend end) {
return UInt32_encodeBinary((const UA_UInt32*)src, NULL, pos, end);
}
static UA_INLINE UA_StatusCode
StatusCode_encodeBinary(UA_StatusCode const *src, bufpos pos, bufend end) {
return UInt32_encodeBinary((const UA_UInt32*)src, NULL, pos, end);
}
static UA_StatusCode
UInt32_decodeBinary(bufpos pos, bufend end, UA_UInt32 *dst, const UA_DataType *_) {
if(*pos + sizeof(UA_UInt32) > end)
return UA_STATUSCODE_BADDECODINGERROR;
#if UA_BINARY_OVERLAYABLE_INTEGER
memcpy(dst, *pos, sizeof(UA_UInt32));
#else
UA_decode32(*pos, dst);
#endif
(*pos) += 4;
return UA_STATUSCODE_GOOD;
}
static UA_INLINE UA_StatusCode
Int32_decodeBinary(bufpos pos, bufend end, UA_Int32 *dst) {
return UInt32_decodeBinary(pos, end, (UA_UInt32*)dst, NULL);
}
static UA_INLINE UA_StatusCode
StatusCode_decodeBinary(bufpos pos, bufend end, UA_StatusCode *dst) {
return UInt32_decodeBinary(pos, end, (UA_UInt32*)dst, NULL);
}
/* UInt64 */
static UA_StatusCode
UInt64_encodeBinary(UA_UInt64 const *src, const UA_DataType *_, bufpos pos, bufend end) {
if(*pos + sizeof(UA_UInt64) > end)
return UA_STATUSCODE_BADENCODINGERROR;
#if UA_BINARY_OVERLAYABLE_INTEGER
memcpy(*pos, src, sizeof(UA_UInt64));
#else
UA_encode64(*src, *pos);
#endif
(*pos) += 8;
return UA_STATUSCODE_GOOD;
}
static UA_INLINE UA_StatusCode
Int64_encodeBinary(UA_Int64 const *src, bufpos pos, bufend end) {
return UInt64_encodeBinary((const UA_UInt64*)src, NULL, pos, end);
}
static UA_INLINE UA_StatusCode
DateTime_encodeBinary(UA_DateTime const *src, bufpos pos, bufend end) {
return UInt64_encodeBinary((const UA_UInt64*)src, NULL, pos, end);
}
static UA_StatusCode
UInt64_decodeBinary(bufpos pos, bufend end, UA_UInt64 *dst, const UA_DataType *_) {
if(*pos + sizeof(UA_UInt64) > end)
return UA_STATUSCODE_BADDECODINGERROR;
#if UA_BINARY_OVERLAYABLE_INTEGER
memcpy(dst, *pos, sizeof(UA_UInt64));
#else
UA_decode64(*pos, dst);
#endif
(*pos) += 8;
return UA_STATUSCODE_GOOD;
}
static UA_INLINE UA_StatusCode
Int64_decodeBinary(bufpos pos, bufend end, UA_Int64 *dst) {
return UInt64_decodeBinary(pos, end, (UA_UInt64*)dst, NULL);
}
static UA_INLINE UA_StatusCode
DateTime_decodeBinary(bufpos pos, bufend end, UA_DateTime *dst) {
return UInt64_decodeBinary(pos, end, (UA_UInt64*)dst, NULL);
}
/************************/
/* 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>
/* 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 exp = shift + ((1<<(expbits-1)) - 1);
return (uint64_t)((sign<<(bits-1)) | (exp<<(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
static UA_StatusCode
Float_encodeBinary(UA_Float const *src, const UA_DataType *_, bufpos pos, bufend end) {
UA_Float f = *src;
UA_UInt32 encoded;
//cppcheck-suppress duplicateExpression
if(f != f) encoded = FLOAT_NAN;
else if(f == 0.0f) encoded = signbit(f) ? FLOAT_NEG_ZERO : 0;
//cppcheck-suppress duplicateExpression
else if(f/f != f/f) encoded = f > 0 ? FLOAT_INF : FLOAT_NEG_INF;
else encoded = (UA_UInt32)pack754(f, 32, 8);
return UInt32_encodeBinary(&encoded, NULL, pos, end);
}
static UA_StatusCode
Float_decodeBinary(bufpos pos, bufend end, UA_Float *dst, const UA_DataType *_) {
UA_UInt32 decoded;
UA_StatusCode retval = UInt32_decodeBinary(pos, end, &decoded, NULL);
if(retval != UA_STATUSCODE_GOOD)
return retval;
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;
if((decoded >= 0x7f800001 && decoded <= 0x7fffffff) ||
(decoded >= 0xff800001 && decoded <= 0xffffffff)) *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
static UA_StatusCode
Double_encodeBinary(UA_Double const *src, const UA_DataType *_, bufpos pos, bufend end) {
UA_Double d = *src;
UA_UInt64 encoded;
//cppcheck-suppress duplicateExpression
if(d != d) encoded = DOUBLE_NAN;
else if(d == 0.0) encoded = signbit(d) ? DOUBLE_NEG_ZERO : 0;
//cppcheck-suppress duplicateExpression
else if(d/d != d/d) encoded = d > 0 ? DOUBLE_INF : DOUBLE_NEG_INF;
else encoded = pack754(d, 64, 11);
return UInt64_encodeBinary(&encoded, NULL, pos, end);
}
static UA_StatusCode
Double_decodeBinary(bufpos pos, bufend end, UA_Double *dst, const UA_DataType *_) {
UA_UInt64 decoded;
UA_StatusCode retval = UInt64_decodeBinary(pos, end, &decoded, NULL);
if(retval != UA_STATUSCODE_GOOD)
return retval;
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;
//cppcheck-suppress redundantCondition
if((decoded >= 0x7ff0000000000001L && decoded <= 0x7fffffffffffffffL) ||
(decoded >= 0xfff0000000000001L && decoded <= 0xffffffffffffffffL)) *dst = NAN;
else *dst = (UA_Double)unpack754(decoded, 64, 11);
return UA_STATUSCODE_GOOD;
}
#endif
/******************/
/* Array Handling */
/******************/
static UA_StatusCode
Array_encodeBinary(const void *src, size_t length, const UA_DataType *type, bufpos pos, bufend end) {
UA_Int32 signed_length = -1;
if(length > UA_INT32_MAX)
return UA_STATUSCODE_BADINTERNALERROR;
if(length > 0)
signed_length = (UA_Int32)length;
else if(src == UA_EMPTY_ARRAY_SENTINEL)
signed_length = 0;
UA_StatusCode retval = Int32_encodeBinary(&signed_length, pos, end);
if(retval != UA_STATUSCODE_GOOD || length == 0)
return retval;
if(type->overlayable) {
size_t i = 0; /* the number of already encoded elements */
while(end < *pos + (type->memSize * (length-i))) {
/* not enough space, need to exchange the buffer */
size_t elements = ((uintptr_t)end - (uintptr_t)*pos) / (sizeof(UA_Byte) * type->memSize);
memcpy(*pos, src, type->memSize * elements);
*pos += type->memSize * elements;
i += elements;
retval = exchangeBuffer(pos, &end);
if(retval != UA_STATUSCODE_GOOD)
return retval;
}
/* encode the remaining elements */
memcpy(*pos, src, type->memSize * (length-i));
*pos += type->memSize * (length-i);
return UA_STATUSCODE_GOOD;
}
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 && retval == UA_STATUSCODE_GOOD; i++) {
UA_Byte *oldpos = *pos;
retval = encodeBinaryJumpTable[encode_index]((const void*)ptr, type, pos, end);
ptr += type->memSize;
if(retval == UA_STATUSCODE_BADENCODINGERROR) {
/* exchange the buffer and try to encode the same element once more */
*pos = oldpos;
retval = exchangeBuffer(pos, &end);
/* Repeat encoding of the same element */
ptr -= type->memSize;
i--;
}
}
return retval;
}
static UA_StatusCode
Array_decodeBinary(bufpos pos, bufend end, UA_Int32 signed_length, void *UA_RESTRICT *UA_RESTRICT dst,
size_t *out_length, const UA_DataType *type) {
*out_length = 0;
if(signed_length <= 0) {
*dst = NULL;
if(signed_length == 0)
*dst = UA_EMPTY_ARRAY_SENTINEL;
return UA_STATUSCODE_GOOD;
}
size_t length = (size_t)signed_length;
/* filter out arrays that can obviously not be parsed, because the message
is too small */
if(*pos + ((type->memSize * length) / 32) > end)
return UA_STATUSCODE_BADDECODINGERROR;
*dst = UA_calloc(1, type->memSize * length);
if(!*dst)
return UA_STATUSCODE_BADOUTOFMEMORY;
if(type->overlayable) {
if(end < *pos + (type->memSize * length))
return UA_STATUSCODE_BADDECODINGERROR;
memcpy(*dst, *pos, type->memSize * length);
(*pos) += type->memSize * length;
*out_length = length;
return UA_STATUSCODE_GOOD;
}
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++) {
UA_StatusCode retval = decodeBinaryJumpTable[decode_index](pos, end, (void*)ptr, type);
if(retval != UA_STATUSCODE_GOOD) {
UA_Array_delete(*dst, i, type);
*dst = NULL;
return retval;
}
ptr += type->memSize;
}
*out_length = length;
return UA_STATUSCODE_GOOD;
}
/*****************/
/* Builtin Types */
/*****************/
static UA_StatusCode
String_encodeBinary(UA_String const *src, const UA_DataType *_, bufpos pos, bufend end) {
return Array_encodeBinary(src->data, src->length, &UA_TYPES[UA_TYPES_BYTE], pos, end);
}
static UA_INLINE UA_StatusCode
ByteString_encodeBinary(UA_ByteString const *src, bufpos pos, bufend end) {
return String_encodeBinary((const UA_String*)src, NULL, pos, end);
}
static UA_StatusCode
String_decodeBinary(bufpos pos, bufend end, UA_String *dst, const UA_DataType *_) {
UA_Int32 signed_length;
UA_StatusCode retval = Int32_decodeBinary(pos, end, &signed_length);
if(retval != UA_STATUSCODE_GOOD)
return UA_STATUSCODE_BADINTERNALERROR;
if(signed_length <= 0) {
if(signed_length == 0)
dst->data = UA_EMPTY_ARRAY_SENTINEL;
else
dst->data = NULL;
return UA_STATUSCODE_GOOD;
}
size_t length = (size_t)signed_length;
if(*pos + length > end)
return UA_STATUSCODE_BADDECODINGERROR;
dst->data = UA_malloc(length);
if(!dst->data)
return UA_STATUSCODE_BADOUTOFMEMORY;
memcpy(dst->data, *pos, length);
dst->length = length;
*pos += length;
return UA_STATUSCODE_GOOD;
}
static UA_INLINE UA_StatusCode
ByteString_decodeBinary(bufpos pos, bufend end, UA_ByteString *dst) {
return String_decodeBinary(pos, end, (UA_ByteString*)dst, NULL);
}
/* Guid */
static UA_StatusCode
Guid_encodeBinary(UA_Guid const *src, const UA_DataType *_, bufpos pos, bufend end) {
UA_StatusCode retval = UInt32_encodeBinary(&src->data1, NULL, pos, end);
retval |= UInt16_encodeBinary(&src->data2, NULL, pos, end);
retval |= UInt16_encodeBinary(&src->data3, NULL, pos, end);
for(UA_Int32 i = 0; i < 8; i++)
retval |= Byte_encodeBinary(&src->data4[i], NULL, pos, end);
return retval;
}
static UA_StatusCode
Guid_decodeBinary(bufpos pos, bufend end, UA_Guid *dst, const UA_DataType *_) {
UA_StatusCode retval = UInt32_decodeBinary(pos, end, &dst->data1, NULL);
retval |= UInt16_decodeBinary(pos, end, &dst->data2, NULL);
retval |= UInt16_decodeBinary(pos, end, &dst->data3, NULL);
for(size_t i = 0; i < 8; i++)
retval |= Byte_decodeBinary(pos, end, &dst->data4[i], NULL);
if(retval != UA_STATUSCODE_GOOD)
UA_Guid_deleteMembers(dst);
return retval;
}
/* NodeId */
#define UA_NODEIDTYPE_NUMERIC_TWOBYTE 0
#define UA_NODEIDTYPE_NUMERIC_FOURBYTE 1
#define UA_NODEIDTYPE_NUMERIC_COMPLETE 2
static UA_StatusCode
NodeId_encodeBinary(UA_NodeId const *src, const UA_DataType *_, bufpos pos, bufend end) {
UA_StatusCode retval = UA_STATUSCODE_GOOD;
// temporary variables for endian-save code
UA_Byte srcByte;
UA_UInt16 srcUInt16;
UA_UInt32 srcUInt32;
switch (src->identifierType) {
case UA_NODEIDTYPE_NUMERIC:
if(src->identifier.numeric > UA_UINT16_MAX || src->namespaceIndex > UA_BYTE_MAX) {
srcByte = UA_NODEIDTYPE_NUMERIC_COMPLETE;
retval |= Byte_encodeBinary(&srcByte, NULL, pos, end);
retval |= UInt16_encodeBinary(&src->namespaceIndex, NULL, pos, end);
srcUInt32 = src->identifier.numeric;
retval |= UInt32_encodeBinary(&srcUInt32, NULL, pos, end);
} else if(src->identifier.numeric > UA_BYTE_MAX || src->namespaceIndex > 0) {
srcByte = UA_NODEIDTYPE_NUMERIC_FOURBYTE;
retval |= Byte_encodeBinary(&srcByte, NULL, pos, end);
srcByte = (UA_Byte)src->namespaceIndex;
srcUInt16 = (UA_UInt16)src->identifier.numeric;
retval |= Byte_encodeBinary(&srcByte, NULL, pos, end);
retval |= UInt16_encodeBinary(&srcUInt16, NULL, pos, end);
} else {
srcByte = UA_NODEIDTYPE_NUMERIC_TWOBYTE;
retval |= Byte_encodeBinary(&srcByte, NULL, pos, end);
srcByte = (UA_Byte)src->identifier.numeric;
retval |= Byte_encodeBinary(&srcByte, NULL, pos, end);
}
break;
case UA_NODEIDTYPE_STRING:
srcByte = UA_NODEIDTYPE_STRING;
retval |= Byte_encodeBinary(&srcByte, NULL, pos, end);
retval |= UInt16_encodeBinary(&src->namespaceIndex, NULL, pos, end);
retval |= String_encodeBinary(&src->identifier.string, NULL, pos, end);
break;
case UA_NODEIDTYPE_GUID:
srcByte = UA_NODEIDTYPE_GUID;
retval |= Byte_encodeBinary(&srcByte, NULL, pos, end);
retval |= UInt16_encodeBinary(&src->namespaceIndex, NULL, pos, end);
retval |= Guid_encodeBinary(&src->identifier.guid, NULL, pos, end);
break;
case UA_NODEIDTYPE_BYTESTRING:
srcByte = UA_NODEIDTYPE_BYTESTRING;
retval |= Byte_encodeBinary(&srcByte, NULL, pos, end);
retval |= UInt16_encodeBinary(&src->namespaceIndex, NULL, pos, end);
retval |= ByteString_encodeBinary(&src->identifier.byteString, pos, end);
break;
default:
return UA_STATUSCODE_BADINTERNALERROR;
}
return retval;
}
static UA_StatusCode
NodeId_decodeBinary(bufpos pos, bufend end, UA_NodeId *dst, const UA_DataType *_) {
UA_Byte dstByte = 0, encodingByte = 0;
UA_UInt16 dstUInt16 = 0;
UA_StatusCode retval = Byte_decodeBinary(pos, end, &encodingByte, NULL);
if(retval != UA_STATUSCODE_GOOD)
return retval;
switch (encodingByte) {
case UA_NODEIDTYPE_NUMERIC_TWOBYTE:
dst->identifierType = UA_NODEIDTYPE_NUMERIC;
retval = Byte_decodeBinary(pos, end, &dstByte, NULL);
dst->identifier.numeric = dstByte;
dst->namespaceIndex = 0;
break;
case UA_NODEIDTYPE_NUMERIC_FOURBYTE:
dst->identifierType = UA_NODEIDTYPE_NUMERIC;
retval |= Byte_decodeBinary(pos, end, &dstByte, NULL);
dst->namespaceIndex = dstByte;
retval |= UInt16_decodeBinary(pos, end, &dstUInt16, NULL);
dst->identifier.numeric = dstUInt16;
break;
case UA_NODEIDTYPE_NUMERIC_COMPLETE:
dst->identifierType = UA_NODEIDTYPE_NUMERIC;
retval |= UInt16_decodeBinary(pos, end, &dst->namespaceIndex, NULL);
retval |= UInt32_decodeBinary(pos, end, &dst->identifier.numeric, NULL);
break;
case UA_NODEIDTYPE_STRING:
dst->identifierType = UA_NODEIDTYPE_STRING;
retval |= UInt16_decodeBinary(pos, end, &dst->namespaceIndex, NULL);
retval |= String_decodeBinary(pos, end, &dst->identifier.string, NULL);
break;
case UA_NODEIDTYPE_GUID:
dst->identifierType = UA_NODEIDTYPE_GUID;
retval |= UInt16_decodeBinary(pos, end, &dst->namespaceIndex, NULL);
retval |= Guid_decodeBinary(pos, end, &dst->identifier.guid, NULL);
break;
case UA_NODEIDTYPE_BYTESTRING:
dst->identifierType = UA_NODEIDTYPE_BYTESTRING;
retval |= UInt16_decodeBinary(pos, end, &dst->namespaceIndex, NULL);
retval |= ByteString_decodeBinary(pos, end, &dst->identifier.byteString);
break;
default:
retval |= UA_STATUSCODE_BADINTERNALERROR; // the client sends an encodingByte we do not recognize
break;
}
if(retval != UA_STATUSCODE_GOOD)
UA_NodeId_deleteMembers(dst);
return retval;
}
/* ExpandedNodeId */
#define UA_EXPANDEDNODEID_NAMESPACEURI_FLAG 0x80
#define UA_EXPANDEDNODEID_SERVERINDEX_FLAG 0x40
static UA_StatusCode
ExpandedNodeId_encodeBinary(UA_ExpandedNodeId const *src, const UA_DataType *_,
bufpos pos, bufend end) {
UA_Byte *start = *pos;
UA_StatusCode retval = NodeId_encodeBinary(&src->nodeId, NULL, pos, end);
if(src->namespaceUri.length > 0) {
retval |= String_encodeBinary(&src->namespaceUri, NULL, pos, end);
*start |= UA_EXPANDEDNODEID_NAMESPACEURI_FLAG;
}
if(src->serverIndex > 0) {
retval |= UInt32_encodeBinary(&src->serverIndex, NULL, pos, end);
*start |= UA_EXPANDEDNODEID_SERVERINDEX_FLAG;
}
return retval;
}
static UA_StatusCode
ExpandedNodeId_decodeBinary(bufpos pos, bufend end, UA_ExpandedNodeId *dst, const UA_DataType *_) {
if(*pos >= end)
return UA_STATUSCODE_BADDECODINGERROR;
UA_Byte encodingByte = **pos;
**pos = encodingByte & (UA_Byte)~(UA_EXPANDEDNODEID_NAMESPACEURI_FLAG | UA_EXPANDEDNODEID_SERVERINDEX_FLAG);
UA_StatusCode retval = NodeId_decodeBinary(pos, end, &dst->nodeId, NULL);
if(encodingByte & UA_EXPANDEDNODEID_NAMESPACEURI_FLAG) {
dst->nodeId.namespaceIndex = 0;
retval |= String_decodeBinary(pos, end, &dst->namespaceUri, NULL);
}
if(encodingByte & UA_EXPANDEDNODEID_SERVERINDEX_FLAG)
retval |= UInt32_decodeBinary(pos, end, &dst->serverIndex, NULL);
if(retval != UA_STATUSCODE_GOOD)
UA_ExpandedNodeId_deleteMembers(dst);
return retval;
}
/* LocalizedText */
#define UA_LOCALIZEDTEXT_ENCODINGMASKTYPE_LOCALE 0x01
#define UA_LOCALIZEDTEXT_ENCODINGMASKTYPE_TEXT 0x02
static UA_StatusCode
LocalizedText_encodeBinary(UA_LocalizedText const *src, const UA_DataType *_, bufpos pos, bufend end) {
UA_Byte encodingMask = 0;
if(src->locale.data)
encodingMask |= UA_LOCALIZEDTEXT_ENCODINGMASKTYPE_LOCALE;
if(src->text.data)
encodingMask |= UA_LOCALIZEDTEXT_ENCODINGMASKTYPE_TEXT;
UA_StatusCode retval = Byte_encodeBinary(&encodingMask, NULL, pos, end);
if(encodingMask & UA_LOCALIZEDTEXT_ENCODINGMASKTYPE_LOCALE)
retval |= String_encodeBinary(&src->locale, NULL, pos, end);
if(encodingMask & UA_LOCALIZEDTEXT_ENCODINGMASKTYPE_TEXT)
retval |= String_encodeBinary(&src->text, NULL, pos, end);
return retval;
}
static UA_StatusCode
LocalizedText_decodeBinary(bufpos pos, bufend end, UA_LocalizedText *dst, const UA_DataType *_) {
UA_Byte encodingMask = 0;
UA_StatusCode retval = Byte_decodeBinary(pos, end, &encodingMask, NULL);
if(encodingMask & UA_LOCALIZEDTEXT_ENCODINGMASKTYPE_LOCALE)
retval |= String_decodeBinary(pos, end, &dst->locale, NULL);
if(encodingMask & UA_LOCALIZEDTEXT_ENCODINGMASKTYPE_TEXT)
retval |= String_decodeBinary(pos, end, &dst->text, NULL);
if(retval != UA_STATUSCODE_GOOD)
UA_LocalizedText_deleteMembers(dst);
return retval;
}
/* ExtensionObject */
static UA_StatusCode
ExtensionObject_encodeBinary(UA_ExtensionObject const *src, const UA_DataType *_, bufpos pos, bufend end) {
UA_StatusCode retval;
UA_Byte encoding = src->encoding;
if(encoding > UA_EXTENSIONOBJECT_ENCODED_XML) {
if(!src->content.decoded.type || !src->content.decoded.data)
return UA_STATUSCODE_BADENCODINGERROR;
UA_NodeId typeId = src->content.decoded.type->typeId;
if(typeId.identifierType != UA_NODEIDTYPE_NUMERIC)
return UA_STATUSCODE_BADENCODINGERROR;
typeId.identifier.numeric += UA_ENCODINGOFFSET_BINARY;
encoding = UA_EXTENSIONOBJECT_ENCODED_BYTESTRING;
retval = NodeId_encodeBinary(&typeId, NULL, pos, end);
retval |= Byte_encodeBinary(&encoding, NULL, pos, end);
UA_Byte *old_pos = *pos; // jump back to encode the length
(*pos) += 4;
const UA_DataType *type = src->content.decoded.type;
size_t encode_index = type->builtin ? type->typeIndex : UA_BUILTIN_TYPES_COUNT;
retval |= encodeBinaryJumpTable[encode_index](src->content.decoded.data, type, pos, end);
UA_Int32 length = (UA_Int32)(((uintptr_t)*pos - (uintptr_t)old_pos) / sizeof(UA_Byte)) - 4;
retval |= Int32_encodeBinary(&length, &old_pos, end);
} else {
retval = NodeId_encodeBinary(&src->content.encoded.typeId, NULL, pos, end);
retval |= Byte_encodeBinary(&encoding, NULL, pos, end);
switch (src->encoding) {
case UA_EXTENSIONOBJECT_ENCODED_NOBODY:
break;
case UA_EXTENSIONOBJECT_ENCODED_BYTESTRING:
case UA_EXTENSIONOBJECT_ENCODED_XML:
retval |= ByteString_encodeBinary(&src->content.encoded.body, pos, end);
break;
default:
return UA_STATUSCODE_BADINTERNALERROR;
}
}
return retval;
}
static UA_StatusCode findDataType(const UA_NodeId *typeId, const UA_DataType **findtype) {
for(size_t i = 0; i < UA_TYPES_COUNT; i++) {
if(UA_NodeId_equal(typeId, &UA_TYPES[i].typeId)) {
*findtype = &UA_TYPES[i];
return UA_STATUSCODE_GOOD;
}
}
return UA_STATUSCODE_BADNODEIDUNKNOWN;
}
static UA_StatusCode
ExtensionObject_decodeBinary(bufpos pos, bufend end, UA_ExtensionObject *dst, const UA_DataType *_) {
UA_Byte encoding = 0;
UA_NodeId typeId;
UA_NodeId_init(&typeId);
UA_StatusCode retval = NodeId_decodeBinary(pos, end, &typeId, NULL);
retval |= Byte_decodeBinary(pos, end, &encoding, NULL);
if(typeId.namespaceIndex != 0 || typeId.identifierType != UA_NODEIDTYPE_NUMERIC)
retval = UA_STATUSCODE_BADDECODINGERROR;
if(retval != UA_STATUSCODE_GOOD) {
UA_NodeId_deleteMembers(&typeId);
return retval;
}
if(encoding == UA_EXTENSIONOBJECT_ENCODED_NOBODY) {
dst->encoding = encoding;
dst->content.encoded.typeId = typeId;
dst->content.encoded.body = UA_BYTESTRING_NULL;
} else if(encoding == UA_EXTENSIONOBJECT_ENCODED_XML) {
dst->encoding = encoding;
dst->content.encoded.typeId = typeId;
retval = ByteString_decodeBinary(pos, end, &dst->content.encoded.body);
} else {
/* try to decode the content */
const UA_DataType *type = NULL;
/* helping clang analyzer, typeId is numeric */
UA_assert(typeId.identifier.byteString.data == NULL);
UA_assert(typeId.identifier.string.data == NULL);
typeId.identifier.numeric -= UA_ENCODINGOFFSET_BINARY;
findDataType(&typeId, &type);
if(type) {
(*pos) += 4; /* jump over the length (todo: check if length matches) */
dst->content.decoded.data = UA_new(type);
size_t decode_index = type->builtin ? type->typeIndex : UA_BUILTIN_TYPES_COUNT;
if(dst->content.decoded.data) {
dst->content.decoded.type = type;
dst->encoding = UA_EXTENSIONOBJECT_DECODED;
retval = decodeBinaryJumpTable[decode_index](pos, end, dst->content.decoded.data, type);
} else
retval = UA_STATUSCODE_BADOUTOFMEMORY;
} else {
retval = ByteString_decodeBinary(pos, end, &dst->content.encoded.body);
dst->encoding = UA_EXTENSIONOBJECT_ENCODED_BYTESTRING;
dst->content.encoded.typeId = typeId;
}
}
if(retval != UA_STATUSCODE_GOOD)
UA_ExtensionObject_deleteMembers(dst);
return retval;
}
/* Variant */
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
};
static UA_StatusCode
Variant_encodeBinary(UA_Variant const *src, const UA_DataType *_, bufpos pos, bufend end) {
if(!src->type)
return UA_STATUSCODE_BADINTERNALERROR;
const UA_Boolean isArray = src->arrayLength > 0 || src->data <= UA_EMPTY_ARRAY_SENTINEL;
const UA_Boolean hasDimensions = isArray && src->arrayDimensionsSize > 0;
const UA_Boolean isBuiltin = src->type->builtin;
/* Encode the encodingbyte */
UA_Byte encodingByte = 0;
if(isArray) {
encodingByte |= UA_VARIANT_ENCODINGMASKTYPE_ARRAY;
if(hasDimensions)
encodingByte |= UA_VARIANT_ENCODINGMASKTYPE_DIMENSIONS;
}
if(isBuiltin)
encodingByte |= UA_VARIANT_ENCODINGMASKTYPE_TYPEID_MASK & (UA_Byte) (src->type->typeIndex + 1);
else
encodingByte |= UA_VARIANT_ENCODINGMASKTYPE_TYPEID_MASK & (UA_Byte) 22; /* ExtensionObject */
UA_StatusCode retval = Byte_encodeBinary(&encodingByte, NULL, pos, end);
/* Encode the content */
if(isBuiltin) {
if(!isArray) {
size_t encode_index = src->type->typeIndex;
retval |= encodeBinaryJumpTable[encode_index](src->data, src->type, pos, end);
} else
retval |= Array_encodeBinary(src->data, src->arrayLength, src->type, pos, end);
} else {
/* Wrap not-builtin elements into an extensionobject */
if(src->arrayDimensionsSize > UA_INT32_MAX)
return UA_STATUSCODE_BADINTERNALERROR;
size_t length = 1;
if(isArray) {
length = src->arrayLength;
UA_Int32 encodedLength = (UA_Int32)src->arrayLength;
retval |= Int32_encodeBinary(&encodedLength, pos, end);
}
UA_ExtensionObject eo;
UA_ExtensionObject_init(&eo);
eo.encoding = UA_EXTENSIONOBJECT_DECODED;
eo.content.decoded.type = src->type;
const UA_UInt16 memSize = src->type->memSize;
uintptr_t ptr = (uintptr_t)src->data;
for(size_t i = 0; i < length && retval == UA_STATUSCODE_GOOD; i++) {
UA_Byte *oldpos = *pos;
eo.content.decoded.data = (void*)ptr;
retval |= ExtensionObject_encodeBinary(&eo, NULL, pos, end);
ptr += memSize;
if(retval == UA_STATUSCODE_BADENCODINGERROR) {
/* exchange/send with the current buffer with chunking */
*pos = oldpos;
retval = exchangeBuffer(pos, &end);
/* encode the same element in the next iteration */
i--;
ptr -= memSize;
}
}
}
/* Encode the dimensions */
if(hasDimensions)
retval |= Array_encodeBinary(src->arrayDimensions, src->arrayDimensionsSize,
&UA_TYPES[UA_TYPES_INT32], pos, end);
return retval;
}
/* The resulting variant always has the storagetype UA_VARIANT_DATA. Currently,
we only support ns0 types (todo: attach typedescriptions to datatypenodes) */
static UA_StatusCode
Variant_decodeBinary(bufpos pos, bufend end, UA_Variant *dst, const UA_DataType *_) {
UA_Byte encodingByte;
UA_StatusCode retval = Byte_decodeBinary(pos, end, &encodingByte, NULL);
if(retval != UA_STATUSCODE_GOOD)
return retval;
UA_Boolean isArray = encodingByte & UA_VARIANT_ENCODINGMASKTYPE_ARRAY;
size_t typeIndex = (size_t)((encodingByte & UA_VARIANT_ENCODINGMASKTYPE_TYPEID_MASK) - 1);
if(typeIndex > 24) /* the type must be builtin (maybe wrapped in an extensionobject) */
return UA_STATUSCODE_BADDECODINGERROR;
if(isArray) {
/* an array */
dst->type = &UA_TYPES[typeIndex];
UA_Int32 signedLength = 0;
retval |= Int32_decodeBinary(pos, end, &signedLength);
if(retval != UA_STATUSCODE_GOOD)
return retval;
retval = Array_decodeBinary(pos, end, signedLength, &dst->data, &dst->arrayLength, dst->type);
} else if (typeIndex != UA_TYPES_EXTENSIONOBJECT) {
/* a builtin type */
dst->type = &UA_TYPES[typeIndex];
retval = Array_decodeBinary(pos, end, 1, &dst->data, &dst->arrayLength, dst->type);
dst->arrayLength = 0;
} else {
/* a single extensionobject */
UA_Byte *old_pos = *pos;
UA_NodeId typeId;
UA_NodeId_init(&typeId);
retval = NodeId_decodeBinary(pos, end, &typeId, NULL);
if(retval != UA_STATUSCODE_GOOD)
return retval;
UA_Byte eo_encoding;
retval = Byte_decodeBinary(pos, end, &eo_encoding, NULL);
if(retval != UA_STATUSCODE_GOOD) {
UA_NodeId_deleteMembers(&typeId);
return retval;
}
/* search for the datatype. use extensionobject if nothing is found */
dst->type = &UA_TYPES[UA_TYPES_EXTENSIONOBJECT];
if(typeId.namespaceIndex == 0 && eo_encoding == UA_EXTENSIONOBJECT_ENCODED_BYTESTRING &&
findDataType(&typeId, &dst->type) == UA_STATUSCODE_GOOD)
*pos = old_pos;
UA_NodeId_deleteMembers(&typeId);
/* decode the type */
dst->data = UA_calloc(1, dst->type->memSize);
if(dst->data) {
size_t decode_index = dst->type->builtin ? dst->type->typeIndex : UA_BUILTIN_TYPES_COUNT;
retval = decodeBinaryJumpTable[decode_index](pos, end, dst->data, dst->type);
if(retval != UA_STATUSCODE_GOOD) {
UA_free(dst->data);
dst->data = NULL;
}
} else
retval = UA_STATUSCODE_BADOUTOFMEMORY;
}
/* array dimensions */
if(isArray && (encodingByte & UA_VARIANT_ENCODINGMASKTYPE_DIMENSIONS)) {
UA_Int32 signed_length = 0;
retval |= Int32_decodeBinary(pos, end, &signed_length);
if(retval == UA_STATUSCODE_GOOD)
retval = Array_decodeBinary(pos, end, signed_length, (void**)&dst->arrayDimensions,
&dst->arrayDimensionsSize, &UA_TYPES[UA_TYPES_INT32]);
}
if(retval != UA_STATUSCODE_GOOD)
UA_Variant_deleteMembers(dst);
return retval;
}
/* DataValue */
static UA_StatusCode
DataValue_encodeBinary(UA_DataValue const *src, const UA_DataType *_, bufpos pos, bufend end) {
UA_Byte encodingMask = (UA_Byte)
(src->hasValue | (src->hasStatus << 1) | (src->hasSourceTimestamp << 2) |
(src->hasServerTimestamp << 3) | (src->hasSourcePicoseconds << 4) |
(src->hasServerPicoseconds << 5));
UA_StatusCode retval = Byte_encodeBinary(&encodingMask, NULL, pos, end);
if(src->hasValue)
retval |= Variant_encodeBinary(&src->value, NULL, pos, end);
if(src->hasStatus)
retval |= StatusCode_encodeBinary(&src->status, pos, end);
if(src->hasSourceTimestamp)
retval |= DateTime_encodeBinary(&src->sourceTimestamp, pos, end);
if(src->hasSourcePicoseconds)
retval |= UInt16_encodeBinary(&src->sourcePicoseconds, NULL, pos, end);
if(src->hasServerTimestamp)
retval |= DateTime_encodeBinary(&src->serverTimestamp, pos, end);
if(src->hasServerPicoseconds)
retval |= UInt16_encodeBinary(&src->serverPicoseconds, NULL, pos, end);
return retval;
}
#define MAX_PICO_SECONDS 999
static UA_StatusCode
DataValue_decodeBinary(bufpos pos, bufend end, UA_DataValue *dst, const UA_DataType *_) {
UA_Byte encodingMask;
UA_StatusCode retval = Byte_decodeBinary(pos, end, &encodingMask, NULL);
if(retval != UA_STATUSCODE_GOOD)
return retval;
if(encodingMask & 0x01) {
dst->hasValue = true;
retval |= Variant_decodeBinary(pos, end, &dst->value, NULL);
}
if(encodingMask & 0x02) {
dst->hasStatus = true;
retval |= StatusCode_decodeBinary(pos, end, &dst->status);
}
if(encodingMask & 0x04) {
dst->hasSourceTimestamp = true;
retval |= DateTime_decodeBinary(pos, end, &dst->sourceTimestamp);
}
if(encodingMask & 0x08) {
dst->hasServerTimestamp = true;
retval |= DateTime_decodeBinary(pos, end, &dst->serverTimestamp);
}
if(encodingMask & 0x10) {
dst->hasSourcePicoseconds = true;
retval |= UInt16_decodeBinary(pos, end, &dst->sourcePicoseconds, NULL);
if(dst->sourcePicoseconds > MAX_PICO_SECONDS)
dst->sourcePicoseconds = MAX_PICO_SECONDS;
}
if(encodingMask & 0x20) {
dst->hasServerPicoseconds = true;
retval |= UInt16_decodeBinary(pos, end, &dst->serverPicoseconds, NULL);
if(dst->serverPicoseconds > MAX_PICO_SECONDS)
dst->serverPicoseconds = MAX_PICO_SECONDS;
}
if(retval != UA_STATUSCODE_GOOD)
UA_DataValue_deleteMembers(dst);
return retval;
}
/* DiagnosticInfo */
static UA_StatusCode
DiagnosticInfo_encodeBinary(const UA_DiagnosticInfo *src, const UA_DataType *_, bufpos pos, bufend end) {
UA_Byte encodingMask = (UA_Byte)
(src->hasSymbolicId | (src->hasNamespaceUri << 1) | (src->hasLocalizedText << 2) |
(src->hasLocale << 3) | (src->hasAdditionalInfo << 4) | (src->hasInnerDiagnosticInfo << 5));
UA_StatusCode retval = Byte_encodeBinary(&encodingMask, NULL, pos, end);
if(src->hasSymbolicId)
retval |= Int32_encodeBinary(&src->symbolicId, pos, end);
if(src->hasNamespaceUri)
retval |= Int32_encodeBinary(&src->namespaceUri, pos, end);
if(src->hasLocalizedText)
retval |= Int32_encodeBinary(&src->localizedText, pos, end);
if(src->hasLocale)
retval |= Int32_encodeBinary(&src->locale, pos, end);
if(src->hasAdditionalInfo)
retval |= String_encodeBinary(&src->additionalInfo, NULL, pos, end);
if(src->hasInnerStatusCode)
retval |= StatusCode_encodeBinary(&src->innerStatusCode, pos, end);
if(src->hasInnerDiagnosticInfo)
retval |= DiagnosticInfo_encodeBinary(src->innerDiagnosticInfo, NULL, pos, end);
return retval;
}
static UA_StatusCode
DiagnosticInfo_decodeBinary(bufpos pos, bufend end, UA_DiagnosticInfo *dst, const UA_DataType *_) {
UA_Byte encodingMask;
UA_StatusCode retval = Byte_decodeBinary(pos, end, &encodingMask, NULL);
if(retval != UA_STATUSCODE_GOOD)
return retval;
if(encodingMask & 0x01) {
dst->hasSymbolicId = true;
retval |= Int32_decodeBinary(pos, end, &dst->symbolicId);
}
if(encodingMask & 0x02) {
dst->hasNamespaceUri = true;
retval |= Int32_decodeBinary(pos, end, &dst->namespaceUri);
}
if(encodingMask & 0x04) {
dst->hasLocalizedText = true;
retval |= Int32_decodeBinary(pos, end, &dst->localizedText);
}
if(encodingMask & 0x08) {
dst->hasLocale = true;
retval |= Int32_decodeBinary(pos, end, &dst->locale);
}
if(encodingMask & 0x10) {
dst->hasAdditionalInfo = true;
retval |= String_decodeBinary(pos, end, &dst->additionalInfo, NULL);
}
if(encodingMask & 0x20) {
dst->hasInnerStatusCode = true;
retval |= StatusCode_decodeBinary(pos, end, &dst->innerStatusCode);
}
if(encodingMask & 0x40) {
dst->hasInnerDiagnosticInfo = true;
/* innerDiagnosticInfo is a pointer to struct, therefore allocate */
dst->innerDiagnosticInfo = UA_calloc(1, sizeof(UA_DiagnosticInfo));
if(dst->innerDiagnosticInfo)
retval |= DiagnosticInfo_decodeBinary(pos, end, dst->innerDiagnosticInfo, NULL);
else {
dst->hasInnerDiagnosticInfo = false;
retval |= UA_STATUSCODE_BADOUTOFMEMORY;
}
}
if(retval != UA_STATUSCODE_GOOD)
UA_DiagnosticInfo_deleteMembers(dst);
return retval;
}
/********************/
/* Structured Types */
/********************/
static UA_StatusCode
UA_encodeBinaryInternal(const void *src, const UA_DataType *type, bufpos pos, bufend end) {
uintptr_t ptr = (uintptr_t)src;
UA_StatusCode retval = UA_STATUSCODE_GOOD;
UA_Byte membersSize = type->membersSize;
const UA_DataType *typelists[2] = { UA_TYPES, &type[-type->typeIndex] };
for(size_t i = 0; i < membersSize && retval == 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;
UA_Byte *oldpos = *pos;
retval |= encodeBinaryJumpTable[encode_index]((const void*)ptr, membertype, pos, end);
ptr += memSize;
if(retval == UA_STATUSCODE_BADENCODINGERROR) {
/* exchange/send the buffer and try to encode the same type once more */
*pos = oldpos;
retval = exchangeBuffer(pos, &end);
/* re-encode the same member on the new buffer */
ptr -= member->padding + memSize;
i--;
}
} else {
ptr += member->padding;
const size_t length = *((const size_t*)ptr);
ptr += sizeof(size_t);
retval |= Array_encodeBinary(*(void *UA_RESTRICT const *)ptr, length, membertype, pos, end);
ptr += sizeof(void*);
}
}
return retval;
}
static const UA_encodeBinarySignature encodeBinaryJumpTable[UA_BUILTIN_TYPES_COUNT + 1] = {
(UA_encodeBinarySignature)Boolean_encodeBinary,
(UA_encodeBinarySignature)Byte_encodeBinary, // SByte
(UA_encodeBinarySignature)Byte_encodeBinary,
(UA_encodeBinarySignature)UInt16_encodeBinary, // Int16
(UA_encodeBinarySignature)UInt16_encodeBinary,
(UA_encodeBinarySignature)UInt32_encodeBinary, // Int32
(UA_encodeBinarySignature)UInt32_encodeBinary,
(UA_encodeBinarySignature)UInt64_encodeBinary, // Int64
(UA_encodeBinarySignature)UInt64_encodeBinary,
(UA_encodeBinarySignature)Float_encodeBinary,
(UA_encodeBinarySignature)Double_encodeBinary,
(UA_encodeBinarySignature)String_encodeBinary,
(UA_encodeBinarySignature)UInt64_encodeBinary, // DateTime
(UA_encodeBinarySignature)Guid_encodeBinary,
(UA_encodeBinarySignature)String_encodeBinary, // ByteString
(UA_encodeBinarySignature)String_encodeBinary, // XmlElement
(UA_encodeBinarySignature)NodeId_encodeBinary,
(UA_encodeBinarySignature)ExpandedNodeId_encodeBinary,
(UA_encodeBinarySignature)UInt32_encodeBinary, // StatusCode
(UA_encodeBinarySignature)UA_encodeBinaryInternal, // QualifiedName
(UA_encodeBinarySignature)LocalizedText_encodeBinary,
(UA_encodeBinarySignature)ExtensionObject_encodeBinary,
(UA_encodeBinarySignature)DataValue_encodeBinary,
(UA_encodeBinarySignature)Variant_encodeBinary,
(UA_encodeBinarySignature)DiagnosticInfo_encodeBinary,
(UA_encodeBinarySignature)UA_encodeBinaryInternal,
};
UA_StatusCode
UA_encodeBinary(const void *src, const UA_DataType *type, UA_exchangeEncodeBuffer callback,
void *handle, UA_ByteString *dst, size_t *offset) {
UA_Byte *pos = &dst->data[*offset];
UA_Byte *end = &dst->data[dst->length];
encodeBuf = dst;
exchangeBufferCallback = callback;
exchangeBufferCallbackHandle = handle;
UA_StatusCode retval = UA_encodeBinaryInternal(src, type, &pos, end);
*offset = (size_t)(pos - dst->data) / sizeof(UA_Byte);
return retval;
}
static UA_StatusCode
UA_decodeBinaryInternal(bufpos pos, bufend end, void *dst, const UA_DataType *type) {
uintptr_t ptr = (uintptr_t)dst;
UA_StatusCode retval = UA_STATUSCODE_GOOD;
UA_Byte 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 fi = membertype->builtin ? membertype->typeIndex : UA_BUILTIN_TYPES_COUNT;
size_t memSize = membertype->memSize;
retval |= decodeBinaryJumpTable[fi](pos, end, (void *UA_RESTRICT)ptr, membertype);
ptr += memSize;
} else {
ptr += member->padding;
size_t *length = (size_t*)ptr;
ptr += sizeof(size_t);
UA_Int32 slength = -1;
retval |= Int32_decodeBinary(pos, end, &slength);
retval |= Array_decodeBinary(pos, end, slength, (void *UA_RESTRICT *UA_RESTRICT)ptr,
length, membertype);
ptr += sizeof(void*);
}
}
if(retval != UA_STATUSCODE_GOOD)
UA_deleteMembers(dst, type);
return retval;
}
static const UA_decodeBinarySignature decodeBinaryJumpTable[UA_BUILTIN_TYPES_COUNT + 1] = {
(UA_decodeBinarySignature)Boolean_decodeBinary,
(UA_decodeBinarySignature)Byte_decodeBinary, // SByte
(UA_decodeBinarySignature)Byte_decodeBinary,
(UA_decodeBinarySignature)UInt16_decodeBinary, // Int16
(UA_decodeBinarySignature)UInt16_decodeBinary,
(UA_decodeBinarySignature)UInt32_decodeBinary, // Int32
(UA_decodeBinarySignature)UInt32_decodeBinary,
(UA_decodeBinarySignature)UInt64_decodeBinary, // Int64
(UA_decodeBinarySignature)UInt64_decodeBinary,
(UA_decodeBinarySignature)Float_decodeBinary,
(UA_decodeBinarySignature)Double_decodeBinary,
(UA_decodeBinarySignature)String_decodeBinary,
(UA_decodeBinarySignature)UInt64_decodeBinary, // DateTime
(UA_decodeBinarySignature)Guid_decodeBinary,
(UA_decodeBinarySignature)String_decodeBinary, // ByteString
(UA_decodeBinarySignature)String_decodeBinary, // XmlElement
(UA_decodeBinarySignature)NodeId_decodeBinary,
(UA_decodeBinarySignature)ExpandedNodeId_decodeBinary,
(UA_decodeBinarySignature)UInt32_decodeBinary, // StatusCode
(UA_decodeBinarySignature)UA_decodeBinaryInternal, // QualifiedName
(UA_decodeBinarySignature)LocalizedText_decodeBinary,
(UA_decodeBinarySignature)ExtensionObject_decodeBinary,
(UA_decodeBinarySignature)DataValue_decodeBinary,
(UA_decodeBinarySignature)Variant_decodeBinary,
(UA_decodeBinarySignature)DiagnosticInfo_decodeBinary,
(UA_decodeBinarySignature)UA_decodeBinaryInternal
};
UA_StatusCode
UA_decodeBinary(const UA_ByteString *src, size_t *offset, void *dst, const UA_DataType *type) {
memset(dst, 0, type->memSize); // init
UA_Byte *pos = &src->data[*offset];
UA_Byte *end = &src->data[src->length];
UA_StatusCode retval = UA_decodeBinaryInternal(&pos, end, dst, type);
*offset = (size_t)(pos - src->data) / sizeof(UA_Byte);
return retval;
}
/******************/
/* CalcSizeBinary */
/******************/
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;
}
static size_t String_calcSizeBinary(const UA_String *UA_RESTRICT p, const UA_DataType *_) {
return 4 + p->length;
}
static size_t Guid_calcSizeBinary(const UA_Guid *UA_RESTRICT p, const UA_DataType *_) {
return 16;
}
static size_t
NodeId_calcSizeBinary(const UA_NodeId *UA_RESTRICT src, const UA_DataType *_) {
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;
}
static size_t
ExpandedNodeId_calcSizeBinary(const UA_ExpandedNodeId *src, const UA_DataType *_) {
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;
}
static size_t
LocalizedText_calcSizeBinary(const UA_LocalizedText *src, UA_DataType *_) {
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;
}
static size_t
ExtensionObject_calcSizeBinary(const UA_ExtensionObject *src, UA_DataType *_) {
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;
}
static size_t
Variant_calcSizeBinary(UA_Variant const *src, UA_DataType *_) {
size_t s = 1; // encoding byte
if(!src->type)
return 0;
UA_Boolean isArray = src->arrayLength > 0 || src->data <= UA_EMPTY_ARRAY_SENTINEL;
UA_Boolean hasDimensions = isArray && src->arrayDimensionsSize > 0;
UA_Boolean isBuiltin = src->type->builtin;
UA_NodeId typeId;
UA_NodeId_init(&typeId);
size_t encode_index = src->type->typeIndex;
if(!isBuiltin) {
encode_index = UA_BUILTIN_TYPES_COUNT;
typeId = src->type->typeId;
if(typeId.identifierType != UA_NODEIDTYPE_NUMERIC)
return 0;
}
size_t length = src->arrayLength;
if(isArray) {
s += 4;
} else
length = 1;
uintptr_t ptr = (uintptr_t)src->data;
size_t memSize = src->type->memSize;
for(size_t i = 0; i < length; i++) {
if(!isBuiltin) {
/* The type is wrapped inside an extensionobject */
s += NodeId_calcSizeBinary(&typeId, NULL);
s += 1 + 4; // encoding byte + length
}
s += calcSizeBinaryJumpTable[encode_index]((const void*)ptr, src->type);
ptr += memSize;
}
if(hasDimensions)
s += Array_calcSizeBinary(src->arrayDimensions, src->arrayDimensionsSize,
&UA_TYPES[UA_TYPES_INT32]);
return s;
}
static size_t
DataValue_calcSizeBinary(const UA_DataValue *src, UA_DataType *_) {
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;
}
static size_t
DiagnosticInfo_calcSizeBinary(const UA_DiagnosticInfo *src, UA_DataType *_) {
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;
}
static const UA_calcSizeBinarySignature calcSizeBinaryJumpTable[UA_BUILTIN_TYPES_COUNT + 1] = {
(UA_calcSizeBinarySignature)calcSizeBinaryMemSize, // Boolean
(UA_calcSizeBinarySignature)calcSizeBinaryMemSize, // Byte
(UA_calcSizeBinarySignature)calcSizeBinaryMemSize,
(UA_calcSizeBinarySignature)calcSizeBinaryMemSize, // Int16
(UA_calcSizeBinarySignature)calcSizeBinaryMemSize,
(UA_calcSizeBinarySignature)calcSizeBinaryMemSize, // Int32
(UA_calcSizeBinarySignature)calcSizeBinaryMemSize,
(UA_calcSizeBinarySignature)calcSizeBinaryMemSize, // Int64
(UA_calcSizeBinarySignature)calcSizeBinaryMemSize,
(UA_calcSizeBinarySignature)calcSizeBinaryMemSize, // Float
(UA_calcSizeBinarySignature)calcSizeBinaryMemSize, // Double
(UA_calcSizeBinarySignature)String_calcSizeBinary,
(UA_calcSizeBinarySignature)calcSizeBinaryMemSize, // DateTime
(UA_calcSizeBinarySignature)Guid_calcSizeBinary,
(UA_calcSizeBinarySignature)String_calcSizeBinary, // ByteString
(UA_calcSizeBinarySignature)String_calcSizeBinary, // XmlElement
(UA_calcSizeBinarySignature)NodeId_calcSizeBinary,
(UA_calcSizeBinarySignature)ExpandedNodeId_calcSizeBinary,
(UA_calcSizeBinarySignature)calcSizeBinaryMemSize, // StatusCode
(UA_calcSizeBinarySignature)UA_calcSizeBinary, // QualifiedName
(UA_calcSizeBinarySignature)LocalizedText_calcSizeBinary,
(UA_calcSizeBinarySignature)ExtensionObject_calcSizeBinary,
(UA_calcSizeBinarySignature)DataValue_calcSizeBinary,
(UA_calcSizeBinarySignature)Variant_calcSizeBinary,
(UA_calcSizeBinarySignature)DiagnosticInfo_calcSizeBinary,
(UA_calcSizeBinarySignature)UA_calcSizeBinary
};
size_t UA_calcSizeBinary(void *p, const UA_DataType *type) {
size_t s = 0;
uintptr_t ptr = (uintptr_t)p;
UA_Byte 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/wn/Sources/open62541-open62541-395ce48/build/src_generated/ua_types_generated.c" ***********************************/
/* Generated from Opc.Ua.Types.bsd with script /home/wn/Sources/open62541-open62541-395ce48/tools/generate_datatypes.py
* on host debianX by user wn at 2016-06-07 04:48:38 */
/* Boolean */
static UA_DataTypeMember Boolean_members[1] = {
{ .memberTypeIndex = UA_TYPES_BOOLEAN,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "",
#endif
.namespaceZero = true,
.padding = 0,
.isArray = false
},};
/* SByte */
static UA_DataTypeMember SByte_members[1] = {
{ .memberTypeIndex = UA_TYPES_SBYTE,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "",
#endif
.namespaceZero = true,
.padding = 0,
.isArray = false
},};
/* Byte */
static UA_DataTypeMember Byte_members[1] = {
{ .memberTypeIndex = UA_TYPES_BYTE,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "",
#endif
.namespaceZero = true,
.padding = 0,
.isArray = false
},};
/* Int16 */
static UA_DataTypeMember Int16_members[1] = {
{ .memberTypeIndex = UA_TYPES_INT16,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "",
#endif
.namespaceZero = true,
.padding = 0,
.isArray = false
},};
/* UInt16 */
static UA_DataTypeMember UInt16_members[1] = {
{ .memberTypeIndex = UA_TYPES_UINT16,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "",
#endif
.namespaceZero = true,
.padding = 0,
.isArray = false
},};
/* Int32 */
static UA_DataTypeMember Int32_members[1] = {
{ .memberTypeIndex = UA_TYPES_INT32,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "",
#endif
.namespaceZero = true,
.padding = 0,
.isArray = false
},};
/* UInt32 */
static UA_DataTypeMember UInt32_members[1] = {
{ .memberTypeIndex = UA_TYPES_UINT32,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "",
#endif
.namespaceZero = true,
.padding = 0,
.isArray = false
},};
/* Int64 */
static UA_DataTypeMember Int64_members[1] = {
{ .memberTypeIndex = UA_TYPES_INT64,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "",
#endif
.namespaceZero = true,
.padding = 0,
.isArray = false
},};
/* UInt64 */
static UA_DataTypeMember UInt64_members[1] = {
{ .memberTypeIndex = UA_TYPES_UINT64,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "",
#endif
.namespaceZero = true,
.padding = 0,
.isArray = false
},};
/* Float */
static UA_DataTypeMember Float_members[1] = {
{ .memberTypeIndex = UA_TYPES_FLOAT,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "",
#endif
.namespaceZero = true,
.padding = 0,
.isArray = false
},};
/* Double */
static UA_DataTypeMember Double_members[1] = {
{ .memberTypeIndex = UA_TYPES_DOUBLE,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "",
#endif
.namespaceZero = true,
.padding = 0,
.isArray = false
},};
/* String */
static UA_DataTypeMember String_members[1] = {
{ .memberTypeIndex = UA_TYPES_BYTE,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "",
#endif
.namespaceZero = true,
.padding = 0,
.isArray = true
},};
/* DateTime */
static UA_DataTypeMember DateTime_members[1] = {
{ .memberTypeIndex = UA_TYPES_DATETIME,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "",
#endif
.namespaceZero = true,
.padding = 0,
.isArray = false
},};
/* Guid */
static UA_DataTypeMember Guid_members[1] = {
{ .memberTypeIndex = UA_TYPES_GUID,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "",
#endif
.namespaceZero = true,
.padding = 0,
.isArray = false
},};
/* ByteString */
static UA_DataTypeMember ByteString_members[1] = {
{ .memberTypeIndex = UA_TYPES_BYTE,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "",
#endif
.namespaceZero = true,
.padding = 0,
.isArray = true
},};
/* XmlElement */
static UA_DataTypeMember XmlElement_members[1] = {
{ .memberTypeIndex = UA_TYPES_BYTE,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "",
#endif
.namespaceZero = true,
.padding = 0,
.isArray = true
},};
/* NodeId */
static UA_DataTypeMember NodeId_members[1] = {
{ .memberTypeIndex = UA_TYPES_NODEID,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "",
#endif
.namespaceZero = true,
.padding = 0,
.isArray = false
},};
/* ExpandedNodeId */
static UA_DataTypeMember ExpandedNodeId_members[1] = {
{ .memberTypeIndex = UA_TYPES_EXPANDEDNODEID,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "",
#endif
.namespaceZero = true,
.padding = 0,
.isArray = false
},};
/* StatusCode */
static UA_DataTypeMember StatusCode_members[1] = {
{ .memberTypeIndex = UA_TYPES_STATUSCODE,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "",
#endif
.namespaceZero = true,
.padding = 0,
.isArray = false
},};
/* QualifiedName */
static UA_DataTypeMember QualifiedName_members[2] = {
{ .memberTypeIndex = UA_TYPES_INT16,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "namespaceIndex",
#endif
.namespaceZero = true,
.padding = 0,
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_STRING,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "name",
#endif
.namespaceZero = true,
.padding = offsetof(UA_QualifiedName, name) - offsetof(UA_QualifiedName, namespaceIndex) - sizeof(UA_Int16),
.isArray = false
},};
/* LocalizedText */
static UA_DataTypeMember LocalizedText_members[1] = {
{ .memberTypeIndex = UA_TYPES_LOCALIZEDTEXT,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "",
#endif
.namespaceZero = true,
.padding = 0,
.isArray = false
},};
/* ExtensionObject */
static UA_DataTypeMember ExtensionObject_members[1] = {
{ .memberTypeIndex = UA_TYPES_EXTENSIONOBJECT,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "",
#endif
.namespaceZero = true,
.padding = 0,
.isArray = false
},};
/* DataValue */
static UA_DataTypeMember DataValue_members[1] = {
{ .memberTypeIndex = UA_TYPES_DATAVALUE,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "",
#endif
.namespaceZero = true,
.padding = 0,
.isArray = false
},};
/* Variant */
static UA_DataTypeMember Variant_members[1] = {
{ .memberTypeIndex = UA_TYPES_VARIANT,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "",
#endif
.namespaceZero = true,
.padding = 0,
.isArray = false
},};
/* DiagnosticInfo */
static UA_DataTypeMember DiagnosticInfo_members[1] = {
{ .memberTypeIndex = UA_TYPES_DIAGNOSTICINFO,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "",
#endif
.namespaceZero = true,
.padding = 0,
.isArray = false
},};
/* SignedSoftwareCertificate */
static UA_DataTypeMember SignedSoftwareCertificate_members[2] = {
{ .memberTypeIndex = UA_TYPES_BYTESTRING,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "certificateData",
#endif
.namespaceZero = true,
.padding = 0,
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_BYTESTRING,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "signature",
#endif
.namespaceZero = true,
.padding = offsetof(UA_SignedSoftwareCertificate, signature) - offsetof(UA_SignedSoftwareCertificate, certificateData) - sizeof(UA_ByteString),
.isArray = false
},};
/* BrowsePathTarget */
static UA_DataTypeMember BrowsePathTarget_members[2] = {
{ .memberTypeIndex = UA_TYPES_EXPANDEDNODEID,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "targetId",
#endif
.namespaceZero = true,
.padding = 0,
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_UINT32,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "remainingPathIndex",
#endif
.namespaceZero = true,
.padding = offsetof(UA_BrowsePathTarget, remainingPathIndex) - offsetof(UA_BrowsePathTarget, targetId) - sizeof(UA_ExpandedNodeId),
.isArray = false
},};
/* ViewAttributes */
static UA_DataTypeMember ViewAttributes_members[7] = {
{ .memberTypeIndex = UA_TYPES_UINT32,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "specifiedAttributes",
#endif
.namespaceZero = true,
.padding = 0,
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_LOCALIZEDTEXT,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "displayName",
#endif
.namespaceZero = true,
.padding = offsetof(UA_ViewAttributes, displayName) - offsetof(UA_ViewAttributes, specifiedAttributes) - sizeof(UA_UInt32),
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_LOCALIZEDTEXT,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "description",
#endif
.namespaceZero = true,
.padding = offsetof(UA_ViewAttributes, description) - offsetof(UA_ViewAttributes, displayName) - sizeof(UA_LocalizedText),
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_UINT32,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "writeMask",
#endif
.namespaceZero = true,
.padding = offsetof(UA_ViewAttributes, writeMask) - offsetof(UA_ViewAttributes, description) - sizeof(UA_LocalizedText),
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_UINT32,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "userWriteMask",
#endif
.namespaceZero = true,
.padding = offsetof(UA_ViewAttributes, userWriteMask) - offsetof(UA_ViewAttributes, writeMask) - sizeof(UA_UInt32),
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_BOOLEAN,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "containsNoLoops",
#endif
.namespaceZero = true,
.padding = offsetof(UA_ViewAttributes, containsNoLoops) - offsetof(UA_ViewAttributes, userWriteMask) - sizeof(UA_UInt32),
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_BYTE,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "eventNotifier",
#endif
.namespaceZero = true,
.padding = offsetof(UA_ViewAttributes, eventNotifier) - offsetof(UA_ViewAttributes, containsNoLoops) - sizeof(UA_Boolean),
.isArray = false
},};
/* BrowseResultMask */
static UA_DataTypeMember BrowseResultMask_members[1] = {
{ .memberTypeIndex = UA_TYPES_INT32,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "",
#endif
.namespaceZero = true,
.padding = 0,
.isArray = false
},};
/* RequestHeader */
static UA_DataTypeMember RequestHeader_members[7] = {
{ .memberTypeIndex = UA_TYPES_NODEID,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "authenticationToken",
#endif
.namespaceZero = true,
.padding = 0,
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_DATETIME,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "timestamp",
#endif
.namespaceZero = true,
.padding = offsetof(UA_RequestHeader, timestamp) - offsetof(UA_RequestHeader, authenticationToken) - sizeof(UA_NodeId),
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_UINT32,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "requestHandle",
#endif
.namespaceZero = true,
.padding = offsetof(UA_RequestHeader, requestHandle) - offsetof(UA_RequestHeader, timestamp) - sizeof(UA_DateTime),
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_UINT32,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "returnDiagnostics",
#endif
.namespaceZero = true,
.padding = offsetof(UA_RequestHeader, returnDiagnostics) - offsetof(UA_RequestHeader, requestHandle) - sizeof(UA_UInt32),
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_STRING,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "auditEntryId",
#endif
.namespaceZero = true,
.padding = offsetof(UA_RequestHeader, auditEntryId) - offsetof(UA_RequestHeader, returnDiagnostics) - sizeof(UA_UInt32),
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_UINT32,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "timeoutHint",
#endif
.namespaceZero = true,
.padding = offsetof(UA_RequestHeader, timeoutHint) - offsetof(UA_RequestHeader, auditEntryId) - sizeof(UA_String),
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_EXTENSIONOBJECT,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "additionalHeader",
#endif
.namespaceZero = true,
.padding = offsetof(UA_RequestHeader, additionalHeader) - offsetof(UA_RequestHeader, timeoutHint) - sizeof(UA_UInt32),
.isArray = false
},};
/* MonitoredItemModifyResult */
static UA_DataTypeMember MonitoredItemModifyResult_members[4] = {
{ .memberTypeIndex = UA_TYPES_STATUSCODE,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "statusCode",
#endif
.namespaceZero = true,
.padding = 0,
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_DOUBLE,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "revisedSamplingInterval",
#endif
.namespaceZero = true,
.padding = offsetof(UA_MonitoredItemModifyResult, revisedSamplingInterval) - offsetof(UA_MonitoredItemModifyResult, statusCode) - sizeof(UA_StatusCode),
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_UINT32,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "revisedQueueSize",
#endif
.namespaceZero = true,
.padding = offsetof(UA_MonitoredItemModifyResult, revisedQueueSize) - offsetof(UA_MonitoredItemModifyResult, revisedSamplingInterval) - sizeof(UA_Double),
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_EXTENSIONOBJECT,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "filterResult",
#endif
.namespaceZero = true,
.padding = offsetof(UA_MonitoredItemModifyResult, filterResult) - offsetof(UA_MonitoredItemModifyResult, revisedQueueSize) - sizeof(UA_UInt32),
.isArray = false
},};
/* ViewDescription */
static UA_DataTypeMember ViewDescription_members[3] = {
{ .memberTypeIndex = UA_TYPES_NODEID,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "viewId",
#endif
.namespaceZero = true,
.padding = 0,
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_DATETIME,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "timestamp",
#endif
.namespaceZero = true,
.padding = offsetof(UA_ViewDescription, timestamp) - offsetof(UA_ViewDescription, viewId) - sizeof(UA_NodeId),
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_UINT32,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "viewVersion",
#endif
.namespaceZero = true,
.padding = offsetof(UA_ViewDescription, viewVersion) - offsetof(UA_ViewDescription, timestamp) - sizeof(UA_DateTime),
.isArray = false
},};
/* CloseSecureChannelRequest */
static UA_DataTypeMember CloseSecureChannelRequest_members[1] = {
{ .memberTypeIndex = UA_TYPES_REQUESTHEADER,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "requestHeader",
#endif
.namespaceZero = true,
.padding = 0,
.isArray = false
},};
/* AddNodesResult */
static UA_DataTypeMember AddNodesResult_members[2] = {
{ .memberTypeIndex = UA_TYPES_STATUSCODE,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "statusCode",
#endif
.namespaceZero = true,
.padding = 0,
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_NODEID,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "addedNodeId",
#endif
.namespaceZero = true,
.padding = offsetof(UA_AddNodesResult, addedNodeId) - offsetof(UA_AddNodesResult, statusCode) - sizeof(UA_StatusCode),
.isArray = false
},};
/* VariableAttributes */
static UA_DataTypeMember VariableAttributes_members[13] = {
{ .memberTypeIndex = UA_TYPES_UINT32,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "specifiedAttributes",
#endif
.namespaceZero = true,
.padding = 0,
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_LOCALIZEDTEXT,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "displayName",
#endif
.namespaceZero = true,
.padding = offsetof(UA_VariableAttributes, displayName) - offsetof(UA_VariableAttributes, specifiedAttributes) - sizeof(UA_UInt32),
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_LOCALIZEDTEXT,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "description",
#endif
.namespaceZero = true,
.padding = offsetof(UA_VariableAttributes, description) - offsetof(UA_VariableAttributes, displayName) - sizeof(UA_LocalizedText),
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_UINT32,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "writeMask",
#endif
.namespaceZero = true,
.padding = offsetof(UA_VariableAttributes, writeMask) - offsetof(UA_VariableAttributes, description) - sizeof(UA_LocalizedText),
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_UINT32,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "userWriteMask",
#endif
.namespaceZero = true,
.padding = offsetof(UA_VariableAttributes, userWriteMask) - offsetof(UA_VariableAttributes, writeMask) - sizeof(UA_UInt32),
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_VARIANT,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "value",
#endif
.namespaceZero = true,
.padding = offsetof(UA_VariableAttributes, value) - offsetof(UA_VariableAttributes, userWriteMask) - sizeof(UA_UInt32),
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_NODEID,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "dataType",
#endif
.namespaceZero = true,
.padding = offsetof(UA_VariableAttributes, dataType) - offsetof(UA_VariableAttributes, value) - sizeof(UA_Variant),
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_INT32,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "valueRank",
#endif
.namespaceZero = true,
.padding = offsetof(UA_VariableAttributes, valueRank) - offsetof(UA_VariableAttributes, dataType) - sizeof(UA_NodeId),
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_UINT32,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "arrayDimensions",
#endif
.namespaceZero = true,
.padding = offsetof(UA_VariableAttributes, arrayDimensionsSize) - offsetof(UA_VariableAttributes, valueRank) - sizeof(UA_Int32),
.isArray = true
},
{ .memberTypeIndex = UA_TYPES_BYTE,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "accessLevel",
#endif
.namespaceZero = true,
.padding = offsetof(UA_VariableAttributes, accessLevel) - offsetof(UA_VariableAttributes, arrayDimensions) - sizeof(void*),
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_BYTE,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "userAccessLevel",
#endif
.namespaceZero = true,
.padding = offsetof(UA_VariableAttributes, userAccessLevel) - offsetof(UA_VariableAttributes, accessLevel) - sizeof(UA_Byte),
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_DOUBLE,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "minimumSamplingInterval",
#endif
.namespaceZero = true,
.padding = offsetof(UA_VariableAttributes, minimumSamplingInterval) - offsetof(UA_VariableAttributes, userAccessLevel) - sizeof(UA_Byte),
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_BOOLEAN,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "historizing",
#endif
.namespaceZero = true,
.padding = offsetof(UA_VariableAttributes, historizing) - offsetof(UA_VariableAttributes, minimumSamplingInterval) - sizeof(UA_Double),
.isArray = false
},};
/* NotificationMessage */
static UA_DataTypeMember NotificationMessage_members[3] = {
{ .memberTypeIndex = UA_TYPES_UINT32,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "sequenceNumber",
#endif
.namespaceZero = true,
.padding = 0,
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_DATETIME,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "publishTime",
#endif
.namespaceZero = true,
.padding = offsetof(UA_NotificationMessage, publishTime) - offsetof(UA_NotificationMessage, sequenceNumber) - sizeof(UA_UInt32),
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_EXTENSIONOBJECT,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "notificationData",
#endif
.namespaceZero = true,
.padding = offsetof(UA_NotificationMessage, notificationDataSize) - offsetof(UA_NotificationMessage, publishTime) - sizeof(UA_DateTime),
.isArray = true
},};
/* NodeAttributesMask */
static UA_DataTypeMember NodeAttributesMask_members[1] = {
{ .memberTypeIndex = UA_TYPES_INT32,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "",
#endif
.namespaceZero = true,
.padding = 0,
.isArray = false
},};
/* MonitoringMode */
static UA_DataTypeMember MonitoringMode_members[1] = {
{ .memberTypeIndex = UA_TYPES_INT32,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "",
#endif
.namespaceZero = true,
.padding = 0,
.isArray = false
},};
/* CallMethodResult */
static UA_DataTypeMember CallMethodResult_members[4] = {
{ .memberTypeIndex = UA_TYPES_STATUSCODE,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "statusCode",
#endif
.namespaceZero = true,
.padding = 0,
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_STATUSCODE,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "inputArgumentResults",
#endif
.namespaceZero = true,
.padding = offsetof(UA_CallMethodResult, inputArgumentResultsSize) - offsetof(UA_CallMethodResult, statusCode) - sizeof(UA_StatusCode),
.isArray = true
},
{ .memberTypeIndex = UA_TYPES_DIAGNOSTICINFO,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "inputArgumentDiagnosticInfos",
#endif
.namespaceZero = true,
.padding = offsetof(UA_CallMethodResult, inputArgumentDiagnosticInfosSize) - offsetof(UA_CallMethodResult, inputArgumentResults) - sizeof(void*),
.isArray = true
},
{ .memberTypeIndex = UA_TYPES_VARIANT,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "outputArguments",
#endif
.namespaceZero = true,
.padding = offsetof(UA_CallMethodResult, outputArgumentsSize) - offsetof(UA_CallMethodResult, inputArgumentDiagnosticInfos) - sizeof(void*),
.isArray = true
},};
/* ParsingResult */
static UA_DataTypeMember ParsingResult_members[3] = {
{ .memberTypeIndex = UA_TYPES_STATUSCODE,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "statusCode",
#endif
.namespaceZero = true,
.padding = 0,
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_STATUSCODE,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "dataStatusCodes",
#endif
.namespaceZero = true,
.padding = offsetof(UA_ParsingResult, dataStatusCodesSize) - offsetof(UA_ParsingResult, statusCode) - sizeof(UA_StatusCode),
.isArray = true
},
{ .memberTypeIndex = UA_TYPES_DIAGNOSTICINFO,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "dataDiagnosticInfos",
#endif
.namespaceZero = true,
.padding = offsetof(UA_ParsingResult, dataDiagnosticInfosSize) - offsetof(UA_ParsingResult, dataStatusCodes) - sizeof(void*),
.isArray = true
},};
/* RelativePathElement */
static UA_DataTypeMember RelativePathElement_members[4] = {
{ .memberTypeIndex = UA_TYPES_NODEID,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "referenceTypeId",
#endif
.namespaceZero = true,
.padding = 0,
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_BOOLEAN,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "isInverse",
#endif
.namespaceZero = true,
.padding = offsetof(UA_RelativePathElement, isInverse) - offsetof(UA_RelativePathElement, referenceTypeId) - sizeof(UA_NodeId),
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_BOOLEAN,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "includeSubtypes",
#endif
.namespaceZero = true,
.padding = offsetof(UA_RelativePathElement, includeSubtypes) - offsetof(UA_RelativePathElement, isInverse) - sizeof(UA_Boolean),
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_QUALIFIEDNAME,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "targetName",
#endif
.namespaceZero = true,
.padding = offsetof(UA_RelativePathElement, targetName) - offsetof(UA_RelativePathElement, includeSubtypes) - sizeof(UA_Boolean),
.isArray = false
},};
/* BrowseDirection */
static UA_DataTypeMember BrowseDirection_members[1] = {
{ .memberTypeIndex = UA_TYPES_INT32,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "",
#endif
.namespaceZero = true,
.padding = 0,
.isArray = false
},};
/* CallMethodRequest */
static UA_DataTypeMember CallMethodRequest_members[3] = {
{ .memberTypeIndex = UA_TYPES_NODEID,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "objectId",
#endif
.namespaceZero = true,
.padding = 0,
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_NODEID,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "methodId",
#endif
.namespaceZero = true,
.padding = offsetof(UA_CallMethodRequest, methodId) - offsetof(UA_CallMethodRequest, objectId) - sizeof(UA_NodeId),
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_VARIANT,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "inputArguments",
#endif
.namespaceZero = true,
.padding = offsetof(UA_CallMethodRequest, inputArgumentsSize) - offsetof(UA_CallMethodRequest, methodId) - sizeof(UA_NodeId),
.isArray = true
},};
/* ServerState */
static UA_DataTypeMember ServerState_members[1] = {
{ .memberTypeIndex = UA_TYPES_INT32,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "",
#endif
.namespaceZero = true,
.padding = 0,
.isArray = false
},};
/* UnregisterNodesRequest */
static UA_DataTypeMember UnregisterNodesRequest_members[2] = {
{ .memberTypeIndex = UA_TYPES_REQUESTHEADER,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "requestHeader",
#endif
.namespaceZero = true,
.padding = 0,
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_NODEID,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "nodesToUnregister",
#endif
.namespaceZero = true,
.padding = offsetof(UA_UnregisterNodesRequest, nodesToUnregisterSize) - offsetof(UA_UnregisterNodesRequest, requestHeader) - sizeof(UA_RequestHeader),
.isArray = true
},};
/* ContentFilterElementResult */
static UA_DataTypeMember ContentFilterElementResult_members[3] = {
{ .memberTypeIndex = UA_TYPES_STATUSCODE,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "statusCode",
#endif
.namespaceZero = true,
.padding = 0,
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_STATUSCODE,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "operandStatusCodes",
#endif
.namespaceZero = true,
.padding = offsetof(UA_ContentFilterElementResult, operandStatusCodesSize) - offsetof(UA_ContentFilterElementResult, statusCode) - sizeof(UA_StatusCode),
.isArray = true
},
{ .memberTypeIndex = UA_TYPES_DIAGNOSTICINFO,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "operandDiagnosticInfos",
#endif
.namespaceZero = true,
.padding = offsetof(UA_ContentFilterElementResult, operandDiagnosticInfosSize) - offsetof(UA_ContentFilterElementResult, operandStatusCodes) - sizeof(void*),
.isArray = true
},};
/* QueryDataSet */
static UA_DataTypeMember QueryDataSet_members[3] = {
{ .memberTypeIndex = UA_TYPES_EXPANDEDNODEID,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "nodeId",
#endif
.namespaceZero = true,
.padding = 0,
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_EXPANDEDNODEID,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "typeDefinitionNode",
#endif
.namespaceZero = true,
.padding = offsetof(UA_QueryDataSet, typeDefinitionNode) - offsetof(UA_QueryDataSet, nodeId) - sizeof(UA_ExpandedNodeId),
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_VARIANT,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "values",
#endif
.namespaceZero = true,
.padding = offsetof(UA_QueryDataSet, valuesSize) - offsetof(UA_QueryDataSet, typeDefinitionNode) - sizeof(UA_ExpandedNodeId),
.isArray = true
},};
/* SetPublishingModeRequest */
static UA_DataTypeMember SetPublishingModeRequest_members[3] = {
{ .memberTypeIndex = UA_TYPES_REQUESTHEADER,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "requestHeader",
#endif
.namespaceZero = true,
.padding = 0,
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_BOOLEAN,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "publishingEnabled",
#endif
.namespaceZero = true,
.padding = offsetof(UA_SetPublishingModeRequest, publishingEnabled) - offsetof(UA_SetPublishingModeRequest, requestHeader) - sizeof(UA_RequestHeader),
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_UINT32,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "subscriptionIds",
#endif
.namespaceZero = true,
.padding = offsetof(UA_SetPublishingModeRequest, subscriptionIdsSize) - offsetof(UA_SetPublishingModeRequest, publishingEnabled) - sizeof(UA_Boolean),
.isArray = true
},};
/* TimestampsToReturn */
static UA_DataTypeMember TimestampsToReturn_members[1] = {
{ .memberTypeIndex = UA_TYPES_INT32,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "",
#endif
.namespaceZero = true,
.padding = 0,
.isArray = false
},};
/* CallRequest */
static UA_DataTypeMember CallRequest_members[2] = {
{ .memberTypeIndex = UA_TYPES_REQUESTHEADER,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "requestHeader",
#endif
.namespaceZero = true,
.padding = 0,
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_CALLMETHODREQUEST,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "methodsToCall",
#endif
.namespaceZero = true,
.padding = offsetof(UA_CallRequest, methodsToCallSize) - offsetof(UA_CallRequest, requestHeader) - sizeof(UA_RequestHeader),
.isArray = true
},};
/* MethodAttributes */
static UA_DataTypeMember MethodAttributes_members[7] = {
{ .memberTypeIndex = UA_TYPES_UINT32,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "specifiedAttributes",
#endif
.namespaceZero = true,
.padding = 0,
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_LOCALIZEDTEXT,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "displayName",
#endif
.namespaceZero = true,
.padding = offsetof(UA_MethodAttributes, displayName) - offsetof(UA_MethodAttributes, specifiedAttributes) - sizeof(UA_UInt32),
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_LOCALIZEDTEXT,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "description",
#endif
.namespaceZero = true,
.padding = offsetof(UA_MethodAttributes, description) - offsetof(UA_MethodAttributes, displayName) - sizeof(UA_LocalizedText),
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_UINT32,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "writeMask",
#endif
.namespaceZero = true,
.padding = offsetof(UA_MethodAttributes, writeMask) - offsetof(UA_MethodAttributes, description) - sizeof(UA_LocalizedText),
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_UINT32,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "userWriteMask",
#endif
.namespaceZero = true,
.padding = offsetof(UA_MethodAttributes, userWriteMask) - offsetof(UA_MethodAttributes, writeMask) - sizeof(UA_UInt32),
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_BOOLEAN,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "executable",
#endif
.namespaceZero = true,
.padding = offsetof(UA_MethodAttributes, executable) - offsetof(UA_MethodAttributes, userWriteMask) - sizeof(UA_UInt32),
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_BOOLEAN,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "userExecutable",
#endif
.namespaceZero = true,
.padding = offsetof(UA_MethodAttributes, userExecutable) - offsetof(UA_MethodAttributes, executable) - sizeof(UA_Boolean),
.isArray = false
},};
/* DeleteReferencesItem */
static UA_DataTypeMember DeleteReferencesItem_members[5] = {
{ .memberTypeIndex = UA_TYPES_NODEID,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "sourceNodeId",
#endif
.namespaceZero = true,
.padding = 0,
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_NODEID,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "referenceTypeId",
#endif
.namespaceZero = true,
.padding = offsetof(UA_DeleteReferencesItem, referenceTypeId) - offsetof(UA_DeleteReferencesItem, sourceNodeId) - sizeof(UA_NodeId),
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_BOOLEAN,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "isForward",
#endif
.namespaceZero = true,
.padding = offsetof(UA_DeleteReferencesItem, isForward) - offsetof(UA_DeleteReferencesItem, referenceTypeId) - sizeof(UA_NodeId),
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_EXPANDEDNODEID,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "targetNodeId",
#endif
.namespaceZero = true,
.padding = offsetof(UA_DeleteReferencesItem, targetNodeId) - offsetof(UA_DeleteReferencesItem, isForward) - sizeof(UA_Boolean),
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_BOOLEAN,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "deleteBidirectional",
#endif
.namespaceZero = true,
.padding = offsetof(UA_DeleteReferencesItem, deleteBidirectional) - offsetof(UA_DeleteReferencesItem, targetNodeId) - sizeof(UA_ExpandedNodeId),
.isArray = false
},};
/* WriteValue */
static UA_DataTypeMember WriteValue_members[4] = {
{ .memberTypeIndex = UA_TYPES_NODEID,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "nodeId",
#endif
.namespaceZero = true,
.padding = 0,
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_UINT32,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "attributeId",
#endif
.namespaceZero = true,
.padding = offsetof(UA_WriteValue, attributeId) - offsetof(UA_WriteValue, nodeId) - sizeof(UA_NodeId),
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_STRING,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "indexRange",
#endif
.namespaceZero = true,
.padding = offsetof(UA_WriteValue, indexRange) - offsetof(UA_WriteValue, attributeId) - sizeof(UA_UInt32),
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_DATAVALUE,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "value",
#endif
.namespaceZero = true,
.padding = offsetof(UA_WriteValue, value) - offsetof(UA_WriteValue, indexRange) - sizeof(UA_String),
.isArray = false
},};
/* MonitoredItemCreateResult */
static UA_DataTypeMember MonitoredItemCreateResult_members[5] = {
{ .memberTypeIndex = UA_TYPES_STATUSCODE,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "statusCode",
#endif
.namespaceZero = true,
.padding = 0,
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_UINT32,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "monitoredItemId",
#endif
.namespaceZero = true,
.padding = offsetof(UA_MonitoredItemCreateResult, monitoredItemId) - offsetof(UA_MonitoredItemCreateResult, statusCode) - sizeof(UA_StatusCode),
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_DOUBLE,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "revisedSamplingInterval",
#endif
.namespaceZero = true,
.padding = offsetof(UA_MonitoredItemCreateResult, revisedSamplingInterval) - offsetof(UA_MonitoredItemCreateResult, monitoredItemId) - sizeof(UA_UInt32),
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_UINT32,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "revisedQueueSize",
#endif
.namespaceZero = true,
.padding = offsetof(UA_MonitoredItemCreateResult, revisedQueueSize) - offsetof(UA_MonitoredItemCreateResult, revisedSamplingInterval) - sizeof(UA_Double),
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_EXTENSIONOBJECT,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "filterResult",
#endif
.namespaceZero = true,
.padding = offsetof(UA_MonitoredItemCreateResult, filterResult) - offsetof(UA_MonitoredItemCreateResult, revisedQueueSize) - sizeof(UA_UInt32),
.isArray = false
},};
/* MessageSecurityMode */
static UA_DataTypeMember MessageSecurityMode_members[1] = {
{ .memberTypeIndex = UA_TYPES_INT32,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "",
#endif
.namespaceZero = true,
.padding = 0,
.isArray = false
},};
/* MonitoringParameters */
static UA_DataTypeMember MonitoringParameters_members[5] = {
{ .memberTypeIndex = UA_TYPES_UINT32,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "clientHandle",
#endif
.namespaceZero = true,
.padding = 0,
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_DOUBLE,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "samplingInterval",
#endif
.namespaceZero = true,
.padding = offsetof(UA_MonitoringParameters, samplingInterval) - offsetof(UA_MonitoringParameters, clientHandle) - sizeof(UA_UInt32),
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_EXTENSIONOBJECT,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "filter",
#endif
.namespaceZero = true,
.padding = offsetof(UA_MonitoringParameters, filter) - offsetof(UA_MonitoringParameters, samplingInterval) - sizeof(UA_Double),
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_UINT32,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "queueSize",
#endif
.namespaceZero = true,
.padding = offsetof(UA_MonitoringParameters, queueSize) - offsetof(UA_MonitoringParameters, filter) - sizeof(UA_ExtensionObject),
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_BOOLEAN,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "discardOldest",
#endif
.namespaceZero = true,
.padding = offsetof(UA_MonitoringParameters, discardOldest) - offsetof(UA_MonitoringParameters, queueSize) - sizeof(UA_UInt32),
.isArray = false
},};
/* SignatureData */
static UA_DataTypeMember SignatureData_members[2] = {
{ .memberTypeIndex = UA_TYPES_STRING,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "algorithm",
#endif
.namespaceZero = true,
.padding = 0,
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_BYTESTRING,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "signature",
#endif
.namespaceZero = true,
.padding = offsetof(UA_SignatureData, signature) - offsetof(UA_SignatureData, algorithm) - sizeof(UA_String),
.isArray = false
},};
/* ReferenceNode */
static UA_DataTypeMember ReferenceNode_members[3] = {
{ .memberTypeIndex = UA_TYPES_NODEID,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "referenceTypeId",
#endif
.namespaceZero = true,
.padding = 0,
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_BOOLEAN,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "isInverse",
#endif
.namespaceZero = true,
.padding = offsetof(UA_ReferenceNode, isInverse) - offsetof(UA_ReferenceNode, referenceTypeId) - sizeof(UA_NodeId),
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_EXPANDEDNODEID,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "targetId",
#endif
.namespaceZero = true,
.padding = offsetof(UA_ReferenceNode, targetId) - offsetof(UA_ReferenceNode, isInverse) - sizeof(UA_Boolean),
.isArray = false
},};
/* Argument */
static UA_DataTypeMember Argument_members[5] = {
{ .memberTypeIndex = UA_TYPES_STRING,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "name",
#endif
.namespaceZero = true,
.padding = 0,
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_NODEID,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "dataType",
#endif
.namespaceZero = true,
.padding = offsetof(UA_Argument, dataType) - offsetof(UA_Argument, name) - sizeof(UA_String),
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_INT32,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "valueRank",
#endif
.namespaceZero = true,
.padding = offsetof(UA_Argument, valueRank) - offsetof(UA_Argument, dataType) - sizeof(UA_NodeId),
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_UINT32,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "arrayDimensions",
#endif
.namespaceZero = true,
.padding = offsetof(UA_Argument, arrayDimensionsSize) - offsetof(UA_Argument, valueRank) - sizeof(UA_Int32),
.isArray = true
},
{ .memberTypeIndex = UA_TYPES_LOCALIZEDTEXT,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "description",
#endif
.namespaceZero = true,
.padding = offsetof(UA_Argument, description) - offsetof(UA_Argument, arrayDimensions) - sizeof(void*),
.isArray = false
},};
/* UserIdentityToken */
static UA_DataTypeMember UserIdentityToken_members[1] = {
{ .memberTypeIndex = UA_TYPES_STRING,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "policyId",
#endif
.namespaceZero = true,
.padding = 0,
.isArray = false
},};
/* ObjectTypeAttributes */
static UA_DataTypeMember ObjectTypeAttributes_members[6] = {
{ .memberTypeIndex = UA_TYPES_UINT32,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "specifiedAttributes",
#endif
.namespaceZero = true,
.padding = 0,
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_LOCALIZEDTEXT,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "displayName",
#endif
.namespaceZero = true,
.padding = offsetof(UA_ObjectTypeAttributes, displayName) - offsetof(UA_ObjectTypeAttributes, specifiedAttributes) - sizeof(UA_UInt32),
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_LOCALIZEDTEXT,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "description",
#endif
.namespaceZero = true,
.padding = offsetof(UA_ObjectTypeAttributes, description) - offsetof(UA_ObjectTypeAttributes, displayName) - sizeof(UA_LocalizedText),
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_UINT32,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "writeMask",
#endif
.namespaceZero = true,
.padding = offsetof(UA_ObjectTypeAttributes, writeMask) - offsetof(UA_ObjectTypeAttributes, description) - sizeof(UA_LocalizedText),
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_UINT32,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "userWriteMask",
#endif
.namespaceZero = true,
.padding = offsetof(UA_ObjectTypeAttributes, userWriteMask) - offsetof(UA_ObjectTypeAttributes, writeMask) - sizeof(UA_UInt32),
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_BOOLEAN,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "isAbstract",
#endif
.namespaceZero = true,
.padding = offsetof(UA_ObjectTypeAttributes, isAbstract) - offsetof(UA_ObjectTypeAttributes, userWriteMask) - sizeof(UA_UInt32),
.isArray = false
},};
/* SecurityTokenRequestType */
static UA_DataTypeMember SecurityTokenRequestType_members[1] = {
{ .memberTypeIndex = UA_TYPES_INT32,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "",
#endif
.namespaceZero = true,
.padding = 0,
.isArray = false
},};
/* BuildInfo */
static UA_DataTypeMember BuildInfo_members[6] = {
{ .memberTypeIndex = UA_TYPES_STRING,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "productUri",
#endif
.namespaceZero = true,
.padding = 0,
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_STRING,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "manufacturerName",
#endif
.namespaceZero = true,
.padding = offsetof(UA_BuildInfo, manufacturerName) - offsetof(UA_BuildInfo, productUri) - sizeof(UA_String),
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_STRING,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "productName",
#endif
.namespaceZero = true,
.padding = offsetof(UA_BuildInfo, productName) - offsetof(UA_BuildInfo, manufacturerName) - sizeof(UA_String),
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_STRING,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "softwareVersion",
#endif
.namespaceZero = true,
.padding = offsetof(UA_BuildInfo, softwareVersion) - offsetof(UA_BuildInfo, productName) - sizeof(UA_String),
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_STRING,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "buildNumber",
#endif
.namespaceZero = true,
.padding = offsetof(UA_BuildInfo, buildNumber) - offsetof(UA_BuildInfo, softwareVersion) - sizeof(UA_String),
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_DATETIME,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "buildDate",
#endif
.namespaceZero = true,
.padding = offsetof(UA_BuildInfo, buildDate) - offsetof(UA_BuildInfo, buildNumber) - sizeof(UA_String),
.isArray = false
},};
/* NodeClass */
static UA_DataTypeMember NodeClass_members[1] = {
{ .memberTypeIndex = UA_TYPES_INT32,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "",
#endif
.namespaceZero = true,
.padding = 0,
.isArray = false
},};
/* ChannelSecurityToken */
static UA_DataTypeMember ChannelSecurityToken_members[4] = {
{ .memberTypeIndex = UA_TYPES_UINT32,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "channelId",
#endif
.namespaceZero = true,
.padding = 0,
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_UINT32,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "tokenId",
#endif
.namespaceZero = true,
.padding = offsetof(UA_ChannelSecurityToken, tokenId) - offsetof(UA_ChannelSecurityToken, channelId) - sizeof(UA_UInt32),
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_DATETIME,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "createdAt",
#endif
.namespaceZero = true,
.padding = offsetof(UA_ChannelSecurityToken, createdAt) - offsetof(UA_ChannelSecurityToken, tokenId) - sizeof(UA_UInt32),
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_UINT32,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "revisedLifetime",
#endif
.namespaceZero = true,
.padding = offsetof(UA_ChannelSecurityToken, revisedLifetime) - offsetof(UA_ChannelSecurityToken, createdAt) - sizeof(UA_DateTime),
.isArray = false
},};
/* MonitoredItemNotification */
static UA_DataTypeMember MonitoredItemNotification_members[2] = {
{ .memberTypeIndex = UA_TYPES_UINT32,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "clientHandle",
#endif
.namespaceZero = true,
.padding = 0,
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_DATAVALUE,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "value",
#endif
.namespaceZero = true,
.padding = offsetof(UA_MonitoredItemNotification, value) - offsetof(UA_MonitoredItemNotification, clientHandle) - sizeof(UA_UInt32),
.isArray = false
},};
/* DeleteNodesItem */
static UA_DataTypeMember DeleteNodesItem_members[2] = {
{ .memberTypeIndex = UA_TYPES_NODEID,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "nodeId",
#endif
.namespaceZero = true,
.padding = 0,
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_BOOLEAN,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "deleteTargetReferences",
#endif
.namespaceZero = true,
.padding = offsetof(UA_DeleteNodesItem, deleteTargetReferences) - offsetof(UA_DeleteNodesItem, nodeId) - sizeof(UA_NodeId),
.isArray = false
},};
/* SubscriptionAcknowledgement */
static UA_DataTypeMember SubscriptionAcknowledgement_members[2] = {
{ .memberTypeIndex = UA_TYPES_UINT32,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "subscriptionId",
#endif
.namespaceZero = true,
.padding = 0,
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_UINT32,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "sequenceNumber",
#endif
.namespaceZero = true,
.padding = offsetof(UA_SubscriptionAcknowledgement, sequenceNumber) - offsetof(UA_SubscriptionAcknowledgement, subscriptionId) - sizeof(UA_UInt32),
.isArray = false
},};
/* ReadValueId */
static UA_DataTypeMember ReadValueId_members[4] = {
{ .memberTypeIndex = UA_TYPES_NODEID,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "nodeId",
#endif
.namespaceZero = true,
.padding = 0,
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_UINT32,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "attributeId",
#endif
.namespaceZero = true,
.padding = offsetof(UA_ReadValueId, attributeId) - offsetof(UA_ReadValueId, nodeId) - sizeof(UA_NodeId),
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_STRING,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "indexRange",
#endif
.namespaceZero = true,
.padding = offsetof(UA_ReadValueId, indexRange) - offsetof(UA_ReadValueId, attributeId) - sizeof(UA_UInt32),
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_QUALIFIEDNAME,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "dataEncoding",
#endif
.namespaceZero = true,
.padding = offsetof(UA_ReadValueId, dataEncoding) - offsetof(UA_ReadValueId, indexRange) - sizeof(UA_String),
.isArray = false
},};
/* AnonymousIdentityToken */
static UA_DataTypeMember AnonymousIdentityToken_members[1] = {
{ .memberTypeIndex = UA_TYPES_STRING,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "policyId",
#endif
.namespaceZero = true,
.padding = 0,
.isArray = false
},};
/* DataTypeAttributes */
static UA_DataTypeMember DataTypeAttributes_members[6] = {
{ .memberTypeIndex = UA_TYPES_UINT32,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "specifiedAttributes",
#endif
.namespaceZero = true,
.padding = 0,
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_LOCALIZEDTEXT,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "displayName",
#endif
.namespaceZero = true,
.padding = offsetof(UA_DataTypeAttributes, displayName) - offsetof(UA_DataTypeAttributes, specifiedAttributes) - sizeof(UA_UInt32),
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_LOCALIZEDTEXT,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "description",
#endif
.namespaceZero = true,
.padding = offsetof(UA_DataTypeAttributes, description) - offsetof(UA_DataTypeAttributes, displayName) - sizeof(UA_LocalizedText),
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_UINT32,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "writeMask",
#endif
.namespaceZero = true,
.padding = offsetof(UA_DataTypeAttributes, writeMask) - offsetof(UA_DataTypeAttributes, description) - sizeof(UA_LocalizedText),
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_UINT32,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "userWriteMask",
#endif
.namespaceZero = true,
.padding = offsetof(UA_DataTypeAttributes, userWriteMask) - offsetof(UA_DataTypeAttributes, writeMask) - sizeof(UA_UInt32),
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_BOOLEAN,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "isAbstract",
#endif
.namespaceZero = true,
.padding = offsetof(UA_DataTypeAttributes, isAbstract) - offsetof(UA_DataTypeAttributes, userWriteMask) - sizeof(UA_UInt32),
.isArray = false
},};
/* ResponseHeader */
static UA_DataTypeMember ResponseHeader_members[6] = {
{ .memberTypeIndex = UA_TYPES_DATETIME,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "timestamp",
#endif
.namespaceZero = true,
.padding = 0,
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_UINT32,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "requestHandle",
#endif
.namespaceZero = true,
.padding = offsetof(UA_ResponseHeader, requestHandle) - offsetof(UA_ResponseHeader, timestamp) - sizeof(UA_DateTime),
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_STATUSCODE,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "serviceResult",
#endif
.namespaceZero = true,
.padding = offsetof(UA_ResponseHeader, serviceResult) - offsetof(UA_ResponseHeader, requestHandle) - sizeof(UA_UInt32),
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_DIAGNOSTICINFO,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "serviceDiagnostics",
#endif
.namespaceZero = true,
.padding = offsetof(UA_ResponseHeader, serviceDiagnostics) - offsetof(UA_ResponseHeader, serviceResult) - sizeof(UA_StatusCode),
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_STRING,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "stringTable",
#endif
.namespaceZero = true,
.padding = offsetof(UA_ResponseHeader, stringTableSize) - offsetof(UA_ResponseHeader, serviceDiagnostics) - sizeof(UA_DiagnosticInfo),
.isArray = true
},
{ .memberTypeIndex = UA_TYPES_EXTENSIONOBJECT,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "additionalHeader",
#endif
.namespaceZero = true,
.padding = offsetof(UA_ResponseHeader, additionalHeader) - offsetof(UA_ResponseHeader, stringTable) - sizeof(void*),
.isArray = false
},};
/* DeleteSubscriptionsRequest */
static UA_DataTypeMember DeleteSubscriptionsRequest_members[2] = {
{ .memberTypeIndex = UA_TYPES_REQUESTHEADER,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "requestHeader",
#endif
.namespaceZero = true,
.padding = 0,
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_UINT32,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "subscriptionIds",
#endif
.namespaceZero = true,
.padding = offsetof(UA_DeleteSubscriptionsRequest, subscriptionIdsSize) - offsetof(UA_DeleteSubscriptionsRequest, requestHeader) - sizeof(UA_RequestHeader),
.isArray = true
},};
/* DataChangeNotification */
static UA_DataTypeMember DataChangeNotification_members[2] = {
{ .memberTypeIndex = UA_TYPES_MONITOREDITEMNOTIFICATION,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "monitoredItems",
#endif
.namespaceZero = true,
.padding = 0,
.isArray = true
},
{ .memberTypeIndex = UA_TYPES_DIAGNOSTICINFO,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "diagnosticInfos",
#endif
.namespaceZero = true,
.padding = offsetof(UA_DataChangeNotification, diagnosticInfosSize) - offsetof(UA_DataChangeNotification, monitoredItems) - sizeof(void*),
.isArray = true
},};
/* DeleteMonitoredItemsResponse */
static UA_DataTypeMember DeleteMonitoredItemsResponse_members[3] = {
{ .memberTypeIndex = UA_TYPES_RESPONSEHEADER,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "responseHeader",
#endif
.namespaceZero = true,
.padding = 0,
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_STATUSCODE,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "results",
#endif
.namespaceZero = true,
.padding = offsetof(UA_DeleteMonitoredItemsResponse, resultsSize) - offsetof(UA_DeleteMonitoredItemsResponse, responseHeader) - sizeof(UA_ResponseHeader),
.isArray = true
},
{ .memberTypeIndex = UA_TYPES_DIAGNOSTICINFO,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "diagnosticInfos",
#endif
.namespaceZero = true,
.padding = offsetof(UA_DeleteMonitoredItemsResponse, diagnosticInfosSize) - offsetof(UA_DeleteMonitoredItemsResponse, results) - sizeof(void*),
.isArray = true
},};
/* RelativePath */
static UA_DataTypeMember RelativePath_members[1] = {
{ .memberTypeIndex = UA_TYPES_RELATIVEPATHELEMENT,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "elements",
#endif
.namespaceZero = true,
.padding = 0,
.isArray = true
},};
/* RegisterNodesRequest */
static UA_DataTypeMember RegisterNodesRequest_members[2] = {
{ .memberTypeIndex = UA_TYPES_REQUESTHEADER,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "requestHeader",
#endif
.namespaceZero = true,
.padding = 0,
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_NODEID,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "nodesToRegister",
#endif
.namespaceZero = true,
.padding = offsetof(UA_RegisterNodesRequest, nodesToRegisterSize) - offsetof(UA_RegisterNodesRequest, requestHeader) - sizeof(UA_RequestHeader),
.isArray = true
},};
/* DeleteNodesRequest */
static UA_DataTypeMember DeleteNodesRequest_members[2] = {
{ .memberTypeIndex = UA_TYPES_REQUESTHEADER,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "requestHeader",
#endif
.namespaceZero = true,
.padding = 0,
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_DELETENODESITEM,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "nodesToDelete",
#endif
.namespaceZero = true,
.padding = offsetof(UA_DeleteNodesRequest, nodesToDeleteSize) - offsetof(UA_DeleteNodesRequest, requestHeader) - sizeof(UA_RequestHeader),
.isArray = true
},};
/* PublishResponse */
static UA_DataTypeMember PublishResponse_members[7] = {
{ .memberTypeIndex = UA_TYPES_RESPONSEHEADER,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "responseHeader",
#endif
.namespaceZero = true,
.padding = 0,
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_UINT32,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "subscriptionId",
#endif
.namespaceZero = true,
.padding = offsetof(UA_PublishResponse, subscriptionId) - offsetof(UA_PublishResponse, responseHeader) - sizeof(UA_ResponseHeader),
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_UINT32,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "availableSequenceNumbers",
#endif
.namespaceZero = true,
.padding = offsetof(UA_PublishResponse, availableSequenceNumbersSize) - offsetof(UA_PublishResponse, subscriptionId) - sizeof(UA_UInt32),
.isArray = true
},
{ .memberTypeIndex = UA_TYPES_BOOLEAN,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "moreNotifications",
#endif
.namespaceZero = true,
.padding = offsetof(UA_PublishResponse, moreNotifications) - offsetof(UA_PublishResponse, availableSequenceNumbers) - sizeof(void*),
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_NOTIFICATIONMESSAGE,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "notificationMessage",
#endif
.namespaceZero = true,
.padding = offsetof(UA_PublishResponse, notificationMessage) - offsetof(UA_PublishResponse, moreNotifications) - sizeof(UA_Boolean),
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_STATUSCODE,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "results",
#endif
.namespaceZero = true,
.padding = offsetof(UA_PublishResponse, resultsSize) - offsetof(UA_PublishResponse, notificationMessage) - sizeof(UA_NotificationMessage),
.isArray = true
},
{ .memberTypeIndex = UA_TYPES_DIAGNOSTICINFO,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "diagnosticInfos",
#endif
.namespaceZero = true,
.padding = offsetof(UA_PublishResponse, diagnosticInfosSize) - offsetof(UA_PublishResponse, results) - sizeof(void*),
.isArray = true
},};
/* MonitoredItemModifyRequest */
static UA_DataTypeMember MonitoredItemModifyRequest_members[2] = {
{ .memberTypeIndex = UA_TYPES_UINT32,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "monitoredItemId",
#endif
.namespaceZero = true,
.padding = 0,
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_MONITORINGPARAMETERS,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "requestedParameters",
#endif
.namespaceZero = true,
.padding = offsetof(UA_MonitoredItemModifyRequest, requestedParameters) - offsetof(UA_MonitoredItemModifyRequest, monitoredItemId) - sizeof(UA_UInt32),
.isArray = false
},};
/* UserNameIdentityToken */
static UA_DataTypeMember UserNameIdentityToken_members[4] = {
{ .memberTypeIndex = UA_TYPES_STRING,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "policyId",
#endif
.namespaceZero = true,
.padding = 0,
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_STRING,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "userName",
#endif
.namespaceZero = true,
.padding = offsetof(UA_UserNameIdentityToken, userName) - offsetof(UA_UserNameIdentityToken, policyId) - sizeof(UA_String),
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_BYTESTRING,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "password",
#endif
.namespaceZero = true,
.padding = offsetof(UA_UserNameIdentityToken, password) - offsetof(UA_UserNameIdentityToken, userName) - sizeof(UA_String),
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_STRING,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "encryptionAlgorithm",
#endif
.namespaceZero = true,
.padding = offsetof(UA_UserNameIdentityToken, encryptionAlgorithm) - offsetof(UA_UserNameIdentityToken, password) - sizeof(UA_ByteString),
.isArray = false
},};
/* IdType */
static UA_DataTypeMember IdType_members[1] = {
{ .memberTypeIndex = UA_TYPES_INT32,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "",
#endif
.namespaceZero = true,
.padding = 0,
.isArray = false
},};
/* UserTokenType */
static UA_DataTypeMember UserTokenType_members[1] = {
{ .memberTypeIndex = UA_TYPES_INT32,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "",
#endif
.namespaceZero = true,
.padding = 0,
.isArray = false
},};
/* NodeAttributes */
static UA_DataTypeMember NodeAttributes_members[5] = {
{ .memberTypeIndex = UA_TYPES_UINT32,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "specifiedAttributes",
#endif
.namespaceZero = true,
.padding = 0,
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_LOCALIZEDTEXT,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "displayName",
#endif
.namespaceZero = true,
.padding = offsetof(UA_NodeAttributes, displayName) - offsetof(UA_NodeAttributes, specifiedAttributes) - sizeof(UA_UInt32),
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_LOCALIZEDTEXT,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "description",
#endif
.namespaceZero = true,
.padding = offsetof(UA_NodeAttributes, description) - offsetof(UA_NodeAttributes, displayName) - sizeof(UA_LocalizedText),
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_UINT32,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "writeMask",
#endif
.namespaceZero = true,
.padding = offsetof(UA_NodeAttributes, writeMask) - offsetof(UA_NodeAttributes, description) - sizeof(UA_LocalizedText),
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_UINT32,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "userWriteMask",
#endif
.namespaceZero = true,
.padding = offsetof(UA_NodeAttributes, userWriteMask) - offsetof(UA_NodeAttributes, writeMask) - sizeof(UA_UInt32),
.isArray = false
},};
/* ActivateSessionRequest */
static UA_DataTypeMember ActivateSessionRequest_members[6] = {
{ .memberTypeIndex = UA_TYPES_REQUESTHEADER,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "requestHeader",
#endif
.namespaceZero = true,
.padding = 0,
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_SIGNATUREDATA,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "clientSignature",
#endif
.namespaceZero = true,
.padding = offsetof(UA_ActivateSessionRequest, clientSignature) - offsetof(UA_ActivateSessionRequest, requestHeader) - sizeof(UA_RequestHeader),
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_SIGNEDSOFTWARECERTIFICATE,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "clientSoftwareCertificates",
#endif
.namespaceZero = true,
.padding = offsetof(UA_ActivateSessionRequest, clientSoftwareCertificatesSize) - offsetof(UA_ActivateSessionRequest, clientSignature) - sizeof(UA_SignatureData),
.isArray = true
},
{ .memberTypeIndex = UA_TYPES_STRING,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "localeIds",
#endif
.namespaceZero = true,
.padding = offsetof(UA_ActivateSessionRequest, localeIdsSize) - offsetof(UA_ActivateSessionRequest, clientSoftwareCertificates) - sizeof(void*),
.isArray = true
},
{ .memberTypeIndex = UA_TYPES_EXTENSIONOBJECT,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "userIdentityToken",
#endif
.namespaceZero = true,
.padding = offsetof(UA_ActivateSessionRequest, userIdentityToken) - offsetof(UA_ActivateSessionRequest, localeIds) - sizeof(void*),
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_SIGNATUREDATA,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "userTokenSignature",
#endif
.namespaceZero = true,
.padding = offsetof(UA_ActivateSessionRequest, userTokenSignature) - offsetof(UA_ActivateSessionRequest, userIdentityToken) - sizeof(UA_ExtensionObject),
.isArray = false
},};
/* OpenSecureChannelResponse */
static UA_DataTypeMember OpenSecureChannelResponse_members[4] = {
{ .memberTypeIndex = UA_TYPES_RESPONSEHEADER,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "responseHeader",
#endif
.namespaceZero = true,
.padding = 0,
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_UINT32,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "serverProtocolVersion",
#endif
.namespaceZero = true,
.padding = offsetof(UA_OpenSecureChannelResponse, serverProtocolVersion) - offsetof(UA_OpenSecureChannelResponse, responseHeader) - sizeof(UA_ResponseHeader),
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_CHANNELSECURITYTOKEN,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "securityToken",
#endif
.namespaceZero = true,
.padding = offsetof(UA_OpenSecureChannelResponse, securityToken) - offsetof(UA_OpenSecureChannelResponse, serverProtocolVersion) - sizeof(UA_UInt32),
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_BYTESTRING,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "serverNonce",
#endif
.namespaceZero = true,
.padding = offsetof(UA_OpenSecureChannelResponse, serverNonce) - offsetof(UA_OpenSecureChannelResponse, securityToken) - sizeof(UA_ChannelSecurityToken),
.isArray = false
},};
/* ApplicationType */
static UA_DataTypeMember ApplicationType_members[1] = {
{ .memberTypeIndex = UA_TYPES_INT32,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "",
#endif
.namespaceZero = true,
.padding = 0,
.isArray = false
},};
/* QueryNextResponse */
static UA_DataTypeMember QueryNextResponse_members[3] = {
{ .memberTypeIndex = UA_TYPES_RESPONSEHEADER,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "responseHeader",
#endif
.namespaceZero = true,
.padding = 0,
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_QUERYDATASET,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "queryDataSets",
#endif
.namespaceZero = true,
.padding = offsetof(UA_QueryNextResponse, queryDataSetsSize) - offsetof(UA_QueryNextResponse, responseHeader) - sizeof(UA_ResponseHeader),
.isArray = true
},
{ .memberTypeIndex = UA_TYPES_BYTESTRING,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "revisedContinuationPoint",
#endif
.namespaceZero = true,
.padding = offsetof(UA_QueryNextResponse, revisedContinuationPoint) - offsetof(UA_QueryNextResponse, queryDataSets) - sizeof(void*),
.isArray = false
},};
/* ActivateSessionResponse */
static UA_DataTypeMember ActivateSessionResponse_members[4] = {
{ .memberTypeIndex = UA_TYPES_RESPONSEHEADER,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "responseHeader",
#endif
.namespaceZero = true,
.padding = 0,
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_BYTESTRING,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "serverNonce",
#endif
.namespaceZero = true,
.padding = offsetof(UA_ActivateSessionResponse, serverNonce) - offsetof(UA_ActivateSessionResponse, responseHeader) - sizeof(UA_ResponseHeader),
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_STATUSCODE,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "results",
#endif
.namespaceZero = true,
.padding = offsetof(UA_ActivateSessionResponse, resultsSize) - offsetof(UA_ActivateSessionResponse, serverNonce) - sizeof(UA_ByteString),
.isArray = true
},
{ .memberTypeIndex = UA_TYPES_DIAGNOSTICINFO,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "diagnosticInfos",
#endif
.namespaceZero = true,
.padding = offsetof(UA_ActivateSessionResponse, diagnosticInfosSize) - offsetof(UA_ActivateSessionResponse, results) - sizeof(void*),
.isArray = true
},};
/* FilterOperator */
static UA_DataTypeMember FilterOperator_members[1] = {
{ .memberTypeIndex = UA_TYPES_INT32,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "",
#endif
.namespaceZero = true,
.padding = 0,
.isArray = false
},};
/* QueryNextRequest */
static UA_DataTypeMember QueryNextRequest_members[3] = {
{ .memberTypeIndex = UA_TYPES_REQUESTHEADER,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "requestHeader",
#endif
.namespaceZero = true,
.padding = 0,
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_BOOLEAN,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "releaseContinuationPoint",
#endif
.namespaceZero = true,
.padding = offsetof(UA_QueryNextRequest, releaseContinuationPoint) - offsetof(UA_QueryNextRequest, requestHeader) - sizeof(UA_RequestHeader),
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_BYTESTRING,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "continuationPoint",
#endif
.namespaceZero = true,
.padding = offsetof(UA_QueryNextRequest, continuationPoint) - offsetof(UA_QueryNextRequest, releaseContinuationPoint) - sizeof(UA_Boolean),
.isArray = false
},};
/* BrowseNextRequest */
static UA_DataTypeMember BrowseNextRequest_members[3] = {
{ .memberTypeIndex = UA_TYPES_REQUESTHEADER,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "requestHeader",
#endif
.namespaceZero = true,
.padding = 0,
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_BOOLEAN,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "releaseContinuationPoints",
#endif
.namespaceZero = true,
.padding = offsetof(UA_BrowseNextRequest, releaseContinuationPoints) - offsetof(UA_BrowseNextRequest, requestHeader) - sizeof(UA_RequestHeader),
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_BYTESTRING,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "continuationPoints",
#endif
.namespaceZero = true,
.padding = offsetof(UA_BrowseNextRequest, continuationPointsSize) - offsetof(UA_BrowseNextRequest, releaseContinuationPoints) - sizeof(UA_Boolean),
.isArray = true
},};
/* CreateSubscriptionRequest */
static UA_DataTypeMember CreateSubscriptionRequest_members[7] = {
{ .memberTypeIndex = UA_TYPES_REQUESTHEADER,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "requestHeader",
#endif
.namespaceZero = true,
.padding = 0,
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_DOUBLE,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "requestedPublishingInterval",
#endif
.namespaceZero = true,
.padding = offsetof(UA_CreateSubscriptionRequest, requestedPublishingInterval) - offsetof(UA_CreateSubscriptionRequest, requestHeader) - sizeof(UA_RequestHeader),
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_UINT32,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "requestedLifetimeCount",
#endif
.namespaceZero = true,
.padding = offsetof(UA_CreateSubscriptionRequest, requestedLifetimeCount) - offsetof(UA_CreateSubscriptionRequest, requestedPublishingInterval) - sizeof(UA_Double),
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_UINT32,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "requestedMaxKeepAliveCount",
#endif
.namespaceZero = true,
.padding = offsetof(UA_CreateSubscriptionRequest, requestedMaxKeepAliveCount) - offsetof(UA_CreateSubscriptionRequest, requestedLifetimeCount) - sizeof(UA_UInt32),
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_UINT32,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "maxNotificationsPerPublish",
#endif
.namespaceZero = true,
.padding = offsetof(UA_CreateSubscriptionRequest, maxNotificationsPerPublish) - offsetof(UA_CreateSubscriptionRequest, requestedMaxKeepAliveCount) - sizeof(UA_UInt32),
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_BOOLEAN,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "publishingEnabled",
#endif
.namespaceZero = true,
.padding = offsetof(UA_CreateSubscriptionRequest, publishingEnabled) - offsetof(UA_CreateSubscriptionRequest, maxNotificationsPerPublish) - sizeof(UA_UInt32),
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_BYTE,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "priority",
#endif
.namespaceZero = true,
.padding = offsetof(UA_CreateSubscriptionRequest, priority) - offsetof(UA_CreateSubscriptionRequest, publishingEnabled) - sizeof(UA_Boolean),
.isArray = false
},};
/* VariableTypeAttributes */
static UA_DataTypeMember VariableTypeAttributes_members[10] = {
{ .memberTypeIndex = UA_TYPES_UINT32,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "specifiedAttributes",
#endif
.namespaceZero = true,
.padding = 0,
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_LOCALIZEDTEXT,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "displayName",
#endif
.namespaceZero = true,
.padding = offsetof(UA_VariableTypeAttributes, displayName) - offsetof(UA_VariableTypeAttributes, specifiedAttributes) - sizeof(UA_UInt32),
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_LOCALIZEDTEXT,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "description",
#endif
.namespaceZero = true,
.padding = offsetof(UA_VariableTypeAttributes, description) - offsetof(UA_VariableTypeAttributes, displayName) - sizeof(UA_LocalizedText),
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_UINT32,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "writeMask",
#endif
.namespaceZero = true,
.padding = offsetof(UA_VariableTypeAttributes, writeMask) - offsetof(UA_VariableTypeAttributes, description) - sizeof(UA_LocalizedText),
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_UINT32,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "userWriteMask",
#endif
.namespaceZero = true,
.padding = offsetof(UA_VariableTypeAttributes, userWriteMask) - offsetof(UA_VariableTypeAttributes, writeMask) - sizeof(UA_UInt32),
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_VARIANT,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "value",
#endif
.namespaceZero = true,
.padding = offsetof(UA_VariableTypeAttributes, value) - offsetof(UA_VariableTypeAttributes, userWriteMask) - sizeof(UA_UInt32),
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_NODEID,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "dataType",
#endif
.namespaceZero = true,
.padding = offsetof(UA_VariableTypeAttributes, dataType) - offsetof(UA_VariableTypeAttributes, value) - sizeof(UA_Variant),
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_INT32,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "valueRank",
#endif
.namespaceZero = true,
.padding = offsetof(UA_VariableTypeAttributes, valueRank) - offsetof(UA_VariableTypeAttributes, dataType) - sizeof(UA_NodeId),
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_UINT32,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "arrayDimensions",
#endif
.namespaceZero = true,
.padding = offsetof(UA_VariableTypeAttributes, arrayDimensionsSize) - offsetof(UA_VariableTypeAttributes, valueRank) - sizeof(UA_Int32),
.isArray = true
},
{ .memberTypeIndex = UA_TYPES_BOOLEAN,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "isAbstract",
#endif
.namespaceZero = true,
.padding = offsetof(UA_VariableTypeAttributes, isAbstract) - offsetof(UA_VariableTypeAttributes, arrayDimensions) - sizeof(void*),
.isArray = false
},};
/* BrowsePathResult */
static UA_DataTypeMember BrowsePathResult_members[2] = {
{ .memberTypeIndex = UA_TYPES_STATUSCODE,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "statusCode",
#endif
.namespaceZero = true,
.padding = 0,
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_BROWSEPATHTARGET,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "targets",
#endif
.namespaceZero = true,
.padding = offsetof(UA_BrowsePathResult, targetsSize) - offsetof(UA_BrowsePathResult, statusCode) - sizeof(UA_StatusCode),
.isArray = true
},};
/* ModifySubscriptionResponse */
static UA_DataTypeMember ModifySubscriptionResponse_members[4] = {
{ .memberTypeIndex = UA_TYPES_RESPONSEHEADER,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "responseHeader",
#endif
.namespaceZero = true,
.padding = 0,
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_DOUBLE,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "revisedPublishingInterval",
#endif
.namespaceZero = true,
.padding = offsetof(UA_ModifySubscriptionResponse, revisedPublishingInterval) - offsetof(UA_ModifySubscriptionResponse, responseHeader) - sizeof(UA_ResponseHeader),
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_UINT32,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "revisedLifetimeCount",
#endif
.namespaceZero = true,
.padding = offsetof(UA_ModifySubscriptionResponse, revisedLifetimeCount) - offsetof(UA_ModifySubscriptionResponse, revisedPublishingInterval) - sizeof(UA_Double),
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_UINT32,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "revisedMaxKeepAliveCount",
#endif
.namespaceZero = true,
.padding = offsetof(UA_ModifySubscriptionResponse, revisedMaxKeepAliveCount) - offsetof(UA_ModifySubscriptionResponse, revisedLifetimeCount) - sizeof(UA_UInt32),
.isArray = false
},};
/* RegisterNodesResponse */
static UA_DataTypeMember RegisterNodesResponse_members[2] = {
{ .memberTypeIndex = UA_TYPES_RESPONSEHEADER,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "responseHeader",
#endif
.namespaceZero = true,
.padding = 0,
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_NODEID,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "registeredNodeIds",
#endif
.namespaceZero = true,
.padding = offsetof(UA_RegisterNodesResponse, registeredNodeIdsSize) - offsetof(UA_RegisterNodesResponse, responseHeader) - sizeof(UA_ResponseHeader),
.isArray = true
},};
/* CloseSessionRequest */
static UA_DataTypeMember CloseSessionRequest_members[2] = {
{ .memberTypeIndex = UA_TYPES_REQUESTHEADER,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "requestHeader",
#endif
.namespaceZero = true,
.padding = 0,
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_BOOLEAN,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "deleteSubscriptions",
#endif
.namespaceZero = true,
.padding = offsetof(UA_CloseSessionRequest, deleteSubscriptions) - offsetof(UA_CloseSessionRequest, requestHeader) - sizeof(UA_RequestHeader),
.isArray = false
},};
/* ModifySubscriptionRequest */
static UA_DataTypeMember ModifySubscriptionRequest_members[7] = {
{ .memberTypeIndex = UA_TYPES_REQUESTHEADER,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "requestHeader",
#endif
.namespaceZero = true,
.padding = 0,
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_UINT32,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "subscriptionId",
#endif
.namespaceZero = true,
.padding = offsetof(UA_ModifySubscriptionRequest, subscriptionId) - offsetof(UA_ModifySubscriptionRequest, requestHeader) - sizeof(UA_RequestHeader),
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_DOUBLE,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "requestedPublishingInterval",
#endif
.namespaceZero = true,
.padding = offsetof(UA_ModifySubscriptionRequest, requestedPublishingInterval) - offsetof(UA_ModifySubscriptionRequest, subscriptionId) - sizeof(UA_UInt32),
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_UINT32,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "requestedLifetimeCount",
#endif
.namespaceZero = true,
.padding = offsetof(UA_ModifySubscriptionRequest, requestedLifetimeCount) - offsetof(UA_ModifySubscriptionRequest, requestedPublishingInterval) - sizeof(UA_Double),
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_UINT32,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "requestedMaxKeepAliveCount",
#endif
.namespaceZero = true,
.padding = offsetof(UA_ModifySubscriptionRequest, requestedMaxKeepAliveCount) - offsetof(UA_ModifySubscriptionRequest, requestedLifetimeCount) - sizeof(UA_UInt32),
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_UINT32,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "maxNotificationsPerPublish",
#endif
.namespaceZero = true,
.padding = offsetof(UA_ModifySubscriptionRequest, maxNotificationsPerPublish) - offsetof(UA_ModifySubscriptionRequest, requestedMaxKeepAliveCount) - sizeof(UA_UInt32),
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_BYTE,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "priority",
#endif
.namespaceZero = true,
.padding = offsetof(UA_ModifySubscriptionRequest, priority) - offsetof(UA_ModifySubscriptionRequest, maxNotificationsPerPublish) - sizeof(UA_UInt32),
.isArray = false
},};
/* UserTokenPolicy */
static UA_DataTypeMember UserTokenPolicy_members[5] = {
{ .memberTypeIndex = UA_TYPES_STRING,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "policyId",
#endif
.namespaceZero = true,
.padding = 0,
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_USERTOKENTYPE,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "tokenType",
#endif
.namespaceZero = true,
.padding = offsetof(UA_UserTokenPolicy, tokenType) - offsetof(UA_UserTokenPolicy, policyId) - sizeof(UA_String),
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_STRING,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "issuedTokenType",
#endif
.namespaceZero = true,
.padding = offsetof(UA_UserTokenPolicy, issuedTokenType) - offsetof(UA_UserTokenPolicy, tokenType) - sizeof(UA_UserTokenType),
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_STRING,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "issuerEndpointUrl",
#endif
.namespaceZero = true,
.padding = offsetof(UA_UserTokenPolicy, issuerEndpointUrl) - offsetof(UA_UserTokenPolicy, issuedTokenType) - sizeof(UA_String),
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_STRING,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "securityPolicyUri",
#endif
.namespaceZero = true,
.padding = offsetof(UA_UserTokenPolicy, securityPolicyUri) - offsetof(UA_UserTokenPolicy, issuerEndpointUrl) - sizeof(UA_String),
.isArray = false
},};
/* DeleteMonitoredItemsRequest */
static UA_DataTypeMember DeleteMonitoredItemsRequest_members[3] = {
{ .memberTypeIndex = UA_TYPES_REQUESTHEADER,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "requestHeader",
#endif
.namespaceZero = true,
.padding = 0,
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_UINT32,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "subscriptionId",
#endif
.namespaceZero = true,
.padding = offsetof(UA_DeleteMonitoredItemsRequest, subscriptionId) - offsetof(UA_DeleteMonitoredItemsRequest, requestHeader) - sizeof(UA_RequestHeader),
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_UINT32,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "monitoredItemIds",
#endif
.namespaceZero = true,
.padding = offsetof(UA_DeleteMonitoredItemsRequest, monitoredItemIdsSize) - offsetof(UA_DeleteMonitoredItemsRequest, subscriptionId) - sizeof(UA_UInt32),
.isArray = true
},};
/* ReferenceTypeAttributes */
static UA_DataTypeMember ReferenceTypeAttributes_members[8] = {
{ .memberTypeIndex = UA_TYPES_UINT32,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "specifiedAttributes",
#endif
.namespaceZero = true,
.padding = 0,
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_LOCALIZEDTEXT,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "displayName",
#endif
.namespaceZero = true,
.padding = offsetof(UA_ReferenceTypeAttributes, displayName) - offsetof(UA_ReferenceTypeAttributes, specifiedAttributes) - sizeof(UA_UInt32),
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_LOCALIZEDTEXT,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "description",
#endif
.namespaceZero = true,
.padding = offsetof(UA_ReferenceTypeAttributes, description) - offsetof(UA_ReferenceTypeAttributes, displayName) - sizeof(UA_LocalizedText),
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_UINT32,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "writeMask",
#endif
.namespaceZero = true,
.padding = offsetof(UA_ReferenceTypeAttributes, writeMask) - offsetof(UA_ReferenceTypeAttributes, description) - sizeof(UA_LocalizedText),
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_UINT32,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "userWriteMask",
#endif
.namespaceZero = true,
.padding = offsetof(UA_ReferenceTypeAttributes, userWriteMask) - offsetof(UA_ReferenceTypeAttributes, writeMask) - sizeof(UA_UInt32),
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_BOOLEAN,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "isAbstract",
#endif
.namespaceZero = true,
.padding = offsetof(UA_ReferenceTypeAttributes, isAbstract) - offsetof(UA_ReferenceTypeAttributes, userWriteMask) - sizeof(UA_UInt32),
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_BOOLEAN,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "symmetric",
#endif
.namespaceZero = true,
.padding = offsetof(UA_ReferenceTypeAttributes, symmetric) - offsetof(UA_ReferenceTypeAttributes, isAbstract) - sizeof(UA_Boolean),
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_LOCALIZEDTEXT,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "inverseName",
#endif
.namespaceZero = true,
.padding = offsetof(UA_ReferenceTypeAttributes, inverseName) - offsetof(UA_ReferenceTypeAttributes, symmetric) - sizeof(UA_Boolean),
.isArray = false
},};
/* BrowsePath */
static UA_DataTypeMember BrowsePath_members[2] = {
{ .memberTypeIndex = UA_TYPES_NODEID,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "startingNode",
#endif
.namespaceZero = true,
.padding = 0,
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_RELATIVEPATH,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "relativePath",
#endif
.namespaceZero = true,
.padding = offsetof(UA_BrowsePath, relativePath) - offsetof(UA_BrowsePath, startingNode) - sizeof(UA_NodeId),
.isArray = false
},};
/* UnregisterNodesResponse */
static UA_DataTypeMember UnregisterNodesResponse_members[1] = {
{ .memberTypeIndex = UA_TYPES_RESPONSEHEADER,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "responseHeader",
#endif
.namespaceZero = true,
.padding = 0,
.isArray = false
},};
/* WriteRequest */
static UA_DataTypeMember WriteRequest_members[2] = {
{ .memberTypeIndex = UA_TYPES_REQUESTHEADER,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "requestHeader",
#endif
.namespaceZero = true,
.padding = 0,
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_WRITEVALUE,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "nodesToWrite",
#endif
.namespaceZero = true,
.padding = offsetof(UA_WriteRequest, nodesToWriteSize) - offsetof(UA_WriteRequest, requestHeader) - sizeof(UA_RequestHeader),
.isArray = true
},};
/* ObjectAttributes */
static UA_DataTypeMember ObjectAttributes_members[6] = {
{ .memberTypeIndex = UA_TYPES_UINT32,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "specifiedAttributes",
#endif
.namespaceZero = true,
.padding = 0,
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_LOCALIZEDTEXT,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "displayName",
#endif
.namespaceZero = true,
.padding = offsetof(UA_ObjectAttributes, displayName) - offsetof(UA_ObjectAttributes, specifiedAttributes) - sizeof(UA_UInt32),
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_LOCALIZEDTEXT,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "description",
#endif
.namespaceZero = true,
.padding = offsetof(UA_ObjectAttributes, description) - offsetof(UA_ObjectAttributes, displayName) - sizeof(UA_LocalizedText),
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_UINT32,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "writeMask",
#endif
.namespaceZero = true,
.padding = offsetof(UA_ObjectAttributes, writeMask) - offsetof(UA_ObjectAttributes, description) - sizeof(UA_LocalizedText),
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_UINT32,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "userWriteMask",
#endif
.namespaceZero = true,
.padding = offsetof(UA_ObjectAttributes, userWriteMask) - offsetof(UA_ObjectAttributes, writeMask) - sizeof(UA_UInt32),
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_BYTE,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "eventNotifier",
#endif
.namespaceZero = true,
.padding = offsetof(UA_ObjectAttributes, eventNotifier) - offsetof(UA_ObjectAttributes, userWriteMask) - sizeof(UA_UInt32),
.isArray = false
},};
/* BrowseDescription */
static UA_DataTypeMember BrowseDescription_members[6] = {
{ .memberTypeIndex = UA_TYPES_NODEID,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "nodeId",
#endif
.namespaceZero = true,
.padding = 0,
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_BROWSEDIRECTION,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "browseDirection",
#endif
.namespaceZero = true,
.padding = offsetof(UA_BrowseDescription, browseDirection) - offsetof(UA_BrowseDescription, nodeId) - sizeof(UA_NodeId),
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_NODEID,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "referenceTypeId",
#endif
.namespaceZero = true,
.padding = offsetof(UA_BrowseDescription, referenceTypeId) - offsetof(UA_BrowseDescription, browseDirection) - sizeof(UA_BrowseDirection),
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_BOOLEAN,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "includeSubtypes",
#endif
.namespaceZero = true,
.padding = offsetof(UA_BrowseDescription, includeSubtypes) - offsetof(UA_BrowseDescription, referenceTypeId) - sizeof(UA_NodeId),
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_UINT32,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "nodeClassMask",
#endif
.namespaceZero = true,
.padding = offsetof(UA_BrowseDescription, nodeClassMask) - offsetof(UA_BrowseDescription, includeSubtypes) - sizeof(UA_Boolean),
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_UINT32,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "resultMask",
#endif
.namespaceZero = true,
.padding = offsetof(UA_BrowseDescription, resultMask) - offsetof(UA_BrowseDescription, nodeClassMask) - sizeof(UA_UInt32),
.isArray = false
},};
/* RepublishRequest */
static UA_DataTypeMember RepublishRequest_members[3] = {
{ .memberTypeIndex = UA_TYPES_REQUESTHEADER,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "requestHeader",
#endif
.namespaceZero = true,
.padding = 0,
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_UINT32,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "subscriptionId",
#endif
.namespaceZero = true,
.padding = offsetof(UA_RepublishRequest, subscriptionId) - offsetof(UA_RepublishRequest, requestHeader) - sizeof(UA_RequestHeader),
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_UINT32,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "retransmitSequenceNumber",
#endif
.namespaceZero = true,
.padding = offsetof(UA_RepublishRequest, retransmitSequenceNumber) - offsetof(UA_RepublishRequest, subscriptionId) - sizeof(UA_UInt32),
.isArray = false
},};
/* GetEndpointsRequest */
static UA_DataTypeMember GetEndpointsRequest_members[4] = {
{ .memberTypeIndex = UA_TYPES_REQUESTHEADER,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "requestHeader",
#endif
.namespaceZero = true,
.padding = 0,
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_STRING,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "endpointUrl",
#endif
.namespaceZero = true,
.padding = offsetof(UA_GetEndpointsRequest, endpointUrl) - offsetof(UA_GetEndpointsRequest, requestHeader) - sizeof(UA_RequestHeader),
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_STRING,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "localeIds",
#endif
.namespaceZero = true,
.padding = offsetof(UA_GetEndpointsRequest, localeIdsSize) - offsetof(UA_GetEndpointsRequest, endpointUrl) - sizeof(UA_String),
.isArray = true
},
{ .memberTypeIndex = UA_TYPES_STRING,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "profileUris",
#endif
.namespaceZero = true,
.padding = offsetof(UA_GetEndpointsRequest, profileUrisSize) - offsetof(UA_GetEndpointsRequest, localeIds) - sizeof(void*),
.isArray = true
},};
/* PublishRequest */
static UA_DataTypeMember PublishRequest_members[2] = {
{ .memberTypeIndex = UA_TYPES_REQUESTHEADER,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "requestHeader",
#endif
.namespaceZero = true,
.padding = 0,
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_SUBSCRIPTIONACKNOWLEDGEMENT,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "subscriptionAcknowledgements",
#endif
.namespaceZero = true,
.padding = offsetof(UA_PublishRequest, subscriptionAcknowledgementsSize) - offsetof(UA_PublishRequest, requestHeader) - sizeof(UA_RequestHeader),
.isArray = true
},};
/* AddNodesResponse */
static UA_DataTypeMember AddNodesResponse_members[3] = {
{ .memberTypeIndex = UA_TYPES_RESPONSEHEADER,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "responseHeader",
#endif
.namespaceZero = true,
.padding = 0,
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_ADDNODESRESULT,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "results",
#endif
.namespaceZero = true,
.padding = offsetof(UA_AddNodesResponse, resultsSize) - offsetof(UA_AddNodesResponse, responseHeader) - sizeof(UA_ResponseHeader),
.isArray = true
},
{ .memberTypeIndex = UA_TYPES_DIAGNOSTICINFO,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "diagnosticInfos",
#endif
.namespaceZero = true,
.padding = offsetof(UA_AddNodesResponse, diagnosticInfosSize) - offsetof(UA_AddNodesResponse, results) - sizeof(void*),
.isArray = true
},};
/* CloseSecureChannelResponse */
static UA_DataTypeMember CloseSecureChannelResponse_members[1] = {
{ .memberTypeIndex = UA_TYPES_RESPONSEHEADER,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "responseHeader",
#endif
.namespaceZero = true,
.padding = 0,
.isArray = false
},};
/* ModifyMonitoredItemsRequest */
static UA_DataTypeMember ModifyMonitoredItemsRequest_members[4] = {
{ .memberTypeIndex = UA_TYPES_REQUESTHEADER,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "requestHeader",
#endif
.namespaceZero = true,
.padding = 0,
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_UINT32,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "subscriptionId",
#endif
.namespaceZero = true,
.padding = offsetof(UA_ModifyMonitoredItemsRequest, subscriptionId) - offsetof(UA_ModifyMonitoredItemsRequest, requestHeader) - sizeof(UA_RequestHeader),
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_TIMESTAMPSTORETURN,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "timestampsToReturn",
#endif
.namespaceZero = true,
.padding = offsetof(UA_ModifyMonitoredItemsRequest, timestampsToReturn) - offsetof(UA_ModifyMonitoredItemsRequest, subscriptionId) - sizeof(UA_UInt32),
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_MONITOREDITEMMODIFYREQUEST,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "itemsToModify",
#endif
.namespaceZero = true,
.padding = offsetof(UA_ModifyMonitoredItemsRequest, itemsToModifySize) - offsetof(UA_ModifyMonitoredItemsRequest, timestampsToReturn) - sizeof(UA_TimestampsToReturn),
.isArray = true
},};
/* FindServersRequest */
static UA_DataTypeMember FindServersRequest_members[4] = {
{ .memberTypeIndex = UA_TYPES_REQUESTHEADER,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "requestHeader",
#endif
.namespaceZero = true,
.padding = 0,
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_STRING,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "endpointUrl",
#endif
.namespaceZero = true,
.padding = offsetof(UA_FindServersRequest, endpointUrl) - offsetof(UA_FindServersRequest, requestHeader) - sizeof(UA_RequestHeader),
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_STRING,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "localeIds",
#endif
.namespaceZero = true,
.padding = offsetof(UA_FindServersRequest, localeIdsSize) - offsetof(UA_FindServersRequest, endpointUrl) - sizeof(UA_String),
.isArray = true
},
{ .memberTypeIndex = UA_TYPES_STRING,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "serverUris",
#endif
.namespaceZero = true,
.padding = offsetof(UA_FindServersRequest, serverUrisSize) - offsetof(UA_FindServersRequest, localeIds) - sizeof(void*),
.isArray = true
},};
/* ReferenceDescription */
static UA_DataTypeMember ReferenceDescription_members[7] = {
{ .memberTypeIndex = UA_TYPES_NODEID,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "referenceTypeId",
#endif
.namespaceZero = true,
.padding = 0,
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_BOOLEAN,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "isForward",
#endif
.namespaceZero = true,
.padding = offsetof(UA_ReferenceDescription, isForward) - offsetof(UA_ReferenceDescription, referenceTypeId) - sizeof(UA_NodeId),
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_EXPANDEDNODEID,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "nodeId",
#endif
.namespaceZero = true,
.padding = offsetof(UA_ReferenceDescription, nodeId) - offsetof(UA_ReferenceDescription, isForward) - sizeof(UA_Boolean),
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_QUALIFIEDNAME,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "browseName",
#endif
.namespaceZero = true,
.padding = offsetof(UA_ReferenceDescription, browseName) - offsetof(UA_ReferenceDescription, nodeId) - sizeof(UA_ExpandedNodeId),
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_LOCALIZEDTEXT,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "displayName",
#endif
.namespaceZero = true,
.padding = offsetof(UA_ReferenceDescription, displayName) - offsetof(UA_ReferenceDescription, browseName) - sizeof(UA_QualifiedName),
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_NODECLASS,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "nodeClass",
#endif
.namespaceZero = true,
.padding = offsetof(UA_ReferenceDescription, nodeClass) - offsetof(UA_ReferenceDescription, displayName) - sizeof(UA_LocalizedText),
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_EXPANDEDNODEID,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "typeDefinition",
#endif
.namespaceZero = true,
.padding = offsetof(UA_ReferenceDescription, typeDefinition) - offsetof(UA_ReferenceDescription, nodeClass) - sizeof(UA_NodeClass),
.isArray = false
},};
/* SetPublishingModeResponse */
static UA_DataTypeMember SetPublishingModeResponse_members[3] = {
{ .memberTypeIndex = UA_TYPES_RESPONSEHEADER,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "responseHeader",
#endif
.namespaceZero = true,
.padding = 0,
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_STATUSCODE,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "results",
#endif
.namespaceZero = true,
.padding = offsetof(UA_SetPublishingModeResponse, resultsSize) - offsetof(UA_SetPublishingModeResponse, responseHeader) - sizeof(UA_ResponseHeader),
.isArray = true
},
{ .memberTypeIndex = UA_TYPES_DIAGNOSTICINFO,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "diagnosticInfos",
#endif
.namespaceZero = true,
.padding = offsetof(UA_SetPublishingModeResponse, diagnosticInfosSize) - offsetof(UA_SetPublishingModeResponse, results) - sizeof(void*),
.isArray = true
},};
/* ContentFilterResult */
static UA_DataTypeMember ContentFilterResult_members[2] = {
{ .memberTypeIndex = UA_TYPES_CONTENTFILTERELEMENTRESULT,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "elementResults",
#endif
.namespaceZero = true,
.padding = 0,
.isArray = true
},
{ .memberTypeIndex = UA_TYPES_DIAGNOSTICINFO,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "elementDiagnosticInfos",
#endif
.namespaceZero = true,
.padding = offsetof(UA_ContentFilterResult, elementDiagnosticInfosSize) - offsetof(UA_ContentFilterResult, elementResults) - sizeof(void*),
.isArray = true
},};
/* AddReferencesItem */
static UA_DataTypeMember AddReferencesItem_members[6] = {
{ .memberTypeIndex = UA_TYPES_NODEID,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "sourceNodeId",
#endif
.namespaceZero = true,
.padding = 0,
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_NODEID,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "referenceTypeId",
#endif
.namespaceZero = true,
.padding = offsetof(UA_AddReferencesItem, referenceTypeId) - offsetof(UA_AddReferencesItem, sourceNodeId) - sizeof(UA_NodeId),
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_BOOLEAN,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "isForward",
#endif
.namespaceZero = true,
.padding = offsetof(UA_AddReferencesItem, isForward) - offsetof(UA_AddReferencesItem, referenceTypeId) - sizeof(UA_NodeId),
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_STRING,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "targetServerUri",
#endif
.namespaceZero = true,
.padding = offsetof(UA_AddReferencesItem, targetServerUri) - offsetof(UA_AddReferencesItem, isForward) - sizeof(UA_Boolean),
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_EXPANDEDNODEID,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "targetNodeId",
#endif
.namespaceZero = true,
.padding = offsetof(UA_AddReferencesItem, targetNodeId) - offsetof(UA_AddReferencesItem, targetServerUri) - sizeof(UA_String),
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_NODECLASS,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "targetNodeClass",
#endif
.namespaceZero = true,
.padding = offsetof(UA_AddReferencesItem, targetNodeClass) - offsetof(UA_AddReferencesItem, targetNodeId) - sizeof(UA_ExpandedNodeId),
.isArray = false
},};
/* QueryDataDescription */
static UA_DataTypeMember QueryDataDescription_members[3] = {
{ .memberTypeIndex = UA_TYPES_RELATIVEPATH,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "relativePath",
#endif
.namespaceZero = true,
.padding = 0,
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_UINT32,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "attributeId",
#endif
.namespaceZero = true,
.padding = offsetof(UA_QueryDataDescription, attributeId) - offsetof(UA_QueryDataDescription, relativePath) - sizeof(UA_RelativePath),
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_STRING,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "indexRange",
#endif
.namespaceZero = true,
.padding = offsetof(UA_QueryDataDescription, indexRange) - offsetof(UA_QueryDataDescription, attributeId) - sizeof(UA_UInt32),
.isArray = false
},};
/* CreateSubscriptionResponse */
static UA_DataTypeMember CreateSubscriptionResponse_members[5] = {
{ .memberTypeIndex = UA_TYPES_RESPONSEHEADER,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "responseHeader",
#endif
.namespaceZero = true,
.padding = 0,
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_UINT32,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "subscriptionId",
#endif
.namespaceZero = true,
.padding = offsetof(UA_CreateSubscriptionResponse, subscriptionId) - offsetof(UA_CreateSubscriptionResponse, responseHeader) - sizeof(UA_ResponseHeader),
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_DOUBLE,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "revisedPublishingInterval",
#endif
.namespaceZero = true,
.padding = offsetof(UA_CreateSubscriptionResponse, revisedPublishingInterval) - offsetof(UA_CreateSubscriptionResponse, subscriptionId) - sizeof(UA_UInt32),
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_UINT32,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "revisedLifetimeCount",
#endif
.namespaceZero = true,
.padding = offsetof(UA_CreateSubscriptionResponse, revisedLifetimeCount) - offsetof(UA_CreateSubscriptionResponse, revisedPublishingInterval) - sizeof(UA_Double),
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_UINT32,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "revisedMaxKeepAliveCount",
#endif
.namespaceZero = true,
.padding = offsetof(UA_CreateSubscriptionResponse, revisedMaxKeepAliveCount) - offsetof(UA_CreateSubscriptionResponse, revisedLifetimeCount) - sizeof(UA_UInt32),
.isArray = false
},};
/* DeleteSubscriptionsResponse */
static UA_DataTypeMember DeleteSubscriptionsResponse_members[3] = {
{ .memberTypeIndex = UA_TYPES_RESPONSEHEADER,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "responseHeader",
#endif
.namespaceZero = true,
.padding = 0,
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_STATUSCODE,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "results",
#endif
.namespaceZero = true,
.padding = offsetof(UA_DeleteSubscriptionsResponse, resultsSize) - offsetof(UA_DeleteSubscriptionsResponse, responseHeader) - sizeof(UA_ResponseHeader),
.isArray = true
},
{ .memberTypeIndex = UA_TYPES_DIAGNOSTICINFO,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "diagnosticInfos",
#endif
.namespaceZero = true,
.padding = offsetof(UA_DeleteSubscriptionsResponse, diagnosticInfosSize) - offsetof(UA_DeleteSubscriptionsResponse, results) - sizeof(void*),
.isArray = true
},};
/* WriteResponse */
static UA_DataTypeMember WriteResponse_members[3] = {
{ .memberTypeIndex = UA_TYPES_RESPONSEHEADER,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "responseHeader",
#endif
.namespaceZero = true,
.padding = 0,
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_STATUSCODE,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "results",
#endif
.namespaceZero = true,
.padding = offsetof(UA_WriteResponse, resultsSize) - offsetof(UA_WriteResponse, responseHeader) - sizeof(UA_ResponseHeader),
.isArray = true
},
{ .memberTypeIndex = UA_TYPES_DIAGNOSTICINFO,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "diagnosticInfos",
#endif
.namespaceZero = true,
.padding = offsetof(UA_WriteResponse, diagnosticInfosSize) - offsetof(UA_WriteResponse, results) - sizeof(void*),
.isArray = true
},};
/* DeleteReferencesResponse */
static UA_DataTypeMember DeleteReferencesResponse_members[3] = {
{ .memberTypeIndex = UA_TYPES_RESPONSEHEADER,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "responseHeader",
#endif
.namespaceZero = true,
.padding = 0,
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_STATUSCODE,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "results",
#endif
.namespaceZero = true,
.padding = offsetof(UA_DeleteReferencesResponse, resultsSize) - offsetof(UA_DeleteReferencesResponse, responseHeader) - sizeof(UA_ResponseHeader),
.isArray = true
},
{ .memberTypeIndex = UA_TYPES_DIAGNOSTICINFO,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "diagnosticInfos",
#endif
.namespaceZero = true,
.padding = offsetof(UA_DeleteReferencesResponse, diagnosticInfosSize) - offsetof(UA_DeleteReferencesResponse, results) - sizeof(void*),
.isArray = true
},};
/* CreateMonitoredItemsResponse */
static UA_DataTypeMember CreateMonitoredItemsResponse_members[3] = {
{ .memberTypeIndex = UA_TYPES_RESPONSEHEADER,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "responseHeader",
#endif
.namespaceZero = true,
.padding = 0,
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_MONITOREDITEMCREATERESULT,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "results",
#endif
.namespaceZero = true,
.padding = offsetof(UA_CreateMonitoredItemsResponse, resultsSize) - offsetof(UA_CreateMonitoredItemsResponse, responseHeader) - sizeof(UA_ResponseHeader),
.isArray = true
},
{ .memberTypeIndex = UA_TYPES_DIAGNOSTICINFO,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "diagnosticInfos",
#endif
.namespaceZero = true,
.padding = offsetof(UA_CreateMonitoredItemsResponse, diagnosticInfosSize) - offsetof(UA_CreateMonitoredItemsResponse, results) - sizeof(void*),
.isArray = true
},};
/* CallResponse */
static UA_DataTypeMember CallResponse_members[3] = {
{ .memberTypeIndex = UA_TYPES_RESPONSEHEADER,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "responseHeader",
#endif
.namespaceZero = true,
.padding = 0,
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_CALLMETHODRESULT,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "results",
#endif
.namespaceZero = true,
.padding = offsetof(UA_CallResponse, resultsSize) - offsetof(UA_CallResponse, responseHeader) - sizeof(UA_ResponseHeader),
.isArray = true
},
{ .memberTypeIndex = UA_TYPES_DIAGNOSTICINFO,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "diagnosticInfos",
#endif
.namespaceZero = true,
.padding = offsetof(UA_CallResponse, diagnosticInfosSize) - offsetof(UA_CallResponse, results) - sizeof(void*),
.isArray = true
},};
/* DeleteNodesResponse */
static UA_DataTypeMember DeleteNodesResponse_members[3] = {
{ .memberTypeIndex = UA_TYPES_RESPONSEHEADER,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "responseHeader",
#endif
.namespaceZero = true,
.padding = 0,
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_STATUSCODE,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "results",
#endif
.namespaceZero = true,
.padding = offsetof(UA_DeleteNodesResponse, resultsSize) - offsetof(UA_DeleteNodesResponse, responseHeader) - sizeof(UA_ResponseHeader),
.isArray = true
},
{ .memberTypeIndex = UA_TYPES_DIAGNOSTICINFO,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "diagnosticInfos",
#endif
.namespaceZero = true,
.padding = offsetof(UA_DeleteNodesResponse, diagnosticInfosSize) - offsetof(UA_DeleteNodesResponse, results) - sizeof(void*),
.isArray = true
},};
/* RepublishResponse */
static UA_DataTypeMember RepublishResponse_members[2] = {
{ .memberTypeIndex = UA_TYPES_RESPONSEHEADER,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "responseHeader",
#endif
.namespaceZero = true,
.padding = 0,
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_NOTIFICATIONMESSAGE,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "notificationMessage",
#endif
.namespaceZero = true,
.padding = offsetof(UA_RepublishResponse, notificationMessage) - offsetof(UA_RepublishResponse, responseHeader) - sizeof(UA_ResponseHeader),
.isArray = false
},};
/* MonitoredItemCreateRequest */
static UA_DataTypeMember MonitoredItemCreateRequest_members[3] = {
{ .memberTypeIndex = UA_TYPES_READVALUEID,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "itemToMonitor",
#endif
.namespaceZero = true,
.padding = 0,
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_MONITORINGMODE,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "monitoringMode",
#endif
.namespaceZero = true,
.padding = offsetof(UA_MonitoredItemCreateRequest, monitoringMode) - offsetof(UA_MonitoredItemCreateRequest, itemToMonitor) - sizeof(UA_ReadValueId),
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_MONITORINGPARAMETERS,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "requestedParameters",
#endif
.namespaceZero = true,
.padding = offsetof(UA_MonitoredItemCreateRequest, requestedParameters) - offsetof(UA_MonitoredItemCreateRequest, monitoringMode) - sizeof(UA_MonitoringMode),
.isArray = false
},};
/* DeleteReferencesRequest */
static UA_DataTypeMember DeleteReferencesRequest_members[2] = {
{ .memberTypeIndex = UA_TYPES_REQUESTHEADER,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "requestHeader",
#endif
.namespaceZero = true,
.padding = 0,
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_DELETEREFERENCESITEM,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "referencesToDelete",
#endif
.namespaceZero = true,
.padding = offsetof(UA_DeleteReferencesRequest, referencesToDeleteSize) - offsetof(UA_DeleteReferencesRequest, requestHeader) - sizeof(UA_RequestHeader),
.isArray = true
},};
/* ModifyMonitoredItemsResponse */
static UA_DataTypeMember ModifyMonitoredItemsResponse_members[3] = {
{ .memberTypeIndex = UA_TYPES_RESPONSEHEADER,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "responseHeader",
#endif
.namespaceZero = true,
.padding = 0,
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_MONITOREDITEMMODIFYRESULT,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "results",
#endif
.namespaceZero = true,
.padding = offsetof(UA_ModifyMonitoredItemsResponse, resultsSize) - offsetof(UA_ModifyMonitoredItemsResponse, responseHeader) - sizeof(UA_ResponseHeader),
.isArray = true
},
{ .memberTypeIndex = UA_TYPES_DIAGNOSTICINFO,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "diagnosticInfos",
#endif
.namespaceZero = true,
.padding = offsetof(UA_ModifyMonitoredItemsResponse, diagnosticInfosSize) - offsetof(UA_ModifyMonitoredItemsResponse, results) - sizeof(void*),
.isArray = true
},};
/* ReadResponse */
static UA_DataTypeMember ReadResponse_members[3] = {
{ .memberTypeIndex = UA_TYPES_RESPONSEHEADER,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "responseHeader",
#endif
.namespaceZero = true,
.padding = 0,
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_DATAVALUE,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "results",
#endif
.namespaceZero = true,
.padding = offsetof(UA_ReadResponse, resultsSize) - offsetof(UA_ReadResponse, responseHeader) - sizeof(UA_ResponseHeader),
.isArray = true
},
{ .memberTypeIndex = UA_TYPES_DIAGNOSTICINFO,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "diagnosticInfos",
#endif
.namespaceZero = true,
.padding = offsetof(UA_ReadResponse, diagnosticInfosSize) - offsetof(UA_ReadResponse, results) - sizeof(void*),
.isArray = true
},};
/* AddReferencesRequest */
static UA_DataTypeMember AddReferencesRequest_members[2] = {
{ .memberTypeIndex = UA_TYPES_REQUESTHEADER,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "requestHeader",
#endif
.namespaceZero = true,
.padding = 0,
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_ADDREFERENCESITEM,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "referencesToAdd",
#endif
.namespaceZero = true,
.padding = offsetof(UA_AddReferencesRequest, referencesToAddSize) - offsetof(UA_AddReferencesRequest, requestHeader) - sizeof(UA_RequestHeader),
.isArray = true
},};
/* ReadRequest */
static UA_DataTypeMember ReadRequest_members[4] = {
{ .memberTypeIndex = UA_TYPES_REQUESTHEADER,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "requestHeader",
#endif
.namespaceZero = true,
.padding = 0,
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_DOUBLE,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "maxAge",
#endif
.namespaceZero = true,
.padding = offsetof(UA_ReadRequest, maxAge) - offsetof(UA_ReadRequest, requestHeader) - sizeof(UA_RequestHeader),
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_TIMESTAMPSTORETURN,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "timestampsToReturn",
#endif
.namespaceZero = true,
.padding = offsetof(UA_ReadRequest, timestampsToReturn) - offsetof(UA_ReadRequest, maxAge) - sizeof(UA_Double),
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_READVALUEID,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "nodesToRead",
#endif
.namespaceZero = true,
.padding = offsetof(UA_ReadRequest, nodesToReadSize) - offsetof(UA_ReadRequest, timestampsToReturn) - sizeof(UA_TimestampsToReturn),
.isArray = true
},};
/* OpenSecureChannelRequest */
static UA_DataTypeMember OpenSecureChannelRequest_members[6] = {
{ .memberTypeIndex = UA_TYPES_REQUESTHEADER,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "requestHeader",
#endif
.namespaceZero = true,
.padding = 0,
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_UINT32,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "clientProtocolVersion",
#endif
.namespaceZero = true,
.padding = offsetof(UA_OpenSecureChannelRequest, clientProtocolVersion) - offsetof(UA_OpenSecureChannelRequest, requestHeader) - sizeof(UA_RequestHeader),
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_SECURITYTOKENREQUESTTYPE,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "requestType",
#endif
.namespaceZero = true,
.padding = offsetof(UA_OpenSecureChannelRequest, requestType) - offsetof(UA_OpenSecureChannelRequest, clientProtocolVersion) - sizeof(UA_UInt32),
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_MESSAGESECURITYMODE,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "securityMode",
#endif
.namespaceZero = true,
.padding = offsetof(UA_OpenSecureChannelRequest, securityMode) - offsetof(UA_OpenSecureChannelRequest, requestType) - sizeof(UA_SecurityTokenRequestType),
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_BYTESTRING,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "clientNonce",
#endif
.namespaceZero = true,
.padding = offsetof(UA_OpenSecureChannelRequest, clientNonce) - offsetof(UA_OpenSecureChannelRequest, securityMode) - sizeof(UA_MessageSecurityMode),
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_UINT32,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "requestedLifetime",
#endif
.namespaceZero = true,
.padding = offsetof(UA_OpenSecureChannelRequest, requestedLifetime) - offsetof(UA_OpenSecureChannelRequest, clientNonce) - sizeof(UA_ByteString),
.isArray = false
},};
/* AddNodesItem */
static UA_DataTypeMember AddNodesItem_members[7] = {
{ .memberTypeIndex = UA_TYPES_EXPANDEDNODEID,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "parentNodeId",
#endif
.namespaceZero = true,
.padding = 0,
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_NODEID,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "referenceTypeId",
#endif
.namespaceZero = true,
.padding = offsetof(UA_AddNodesItem, referenceTypeId) - offsetof(UA_AddNodesItem, parentNodeId) - sizeof(UA_ExpandedNodeId),
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_EXPANDEDNODEID,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "requestedNewNodeId",
#endif
.namespaceZero = true,
.padding = offsetof(UA_AddNodesItem, requestedNewNodeId) - offsetof(UA_AddNodesItem, referenceTypeId) - sizeof(UA_NodeId),
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_QUALIFIEDNAME,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "browseName",
#endif
.namespaceZero = true,
.padding = offsetof(UA_AddNodesItem, browseName) - offsetof(UA_AddNodesItem, requestedNewNodeId) - sizeof(UA_ExpandedNodeId),
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_NODECLASS,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "nodeClass",
#endif
.namespaceZero = true,
.padding = offsetof(UA_AddNodesItem, nodeClass) - offsetof(UA_AddNodesItem, browseName) - sizeof(UA_QualifiedName),
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_EXTENSIONOBJECT,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "nodeAttributes",
#endif
.namespaceZero = true,
.padding = offsetof(UA_AddNodesItem, nodeAttributes) - offsetof(UA_AddNodesItem, nodeClass) - sizeof(UA_NodeClass),
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_EXPANDEDNODEID,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "typeDefinition",
#endif
.namespaceZero = true,
.padding = offsetof(UA_AddNodesItem, typeDefinition) - offsetof(UA_AddNodesItem, nodeAttributes) - sizeof(UA_ExtensionObject),
.isArray = false
},};
/* ApplicationDescription */
static UA_DataTypeMember ApplicationDescription_members[7] = {
{ .memberTypeIndex = UA_TYPES_STRING,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "applicationUri",
#endif
.namespaceZero = true,
.padding = 0,
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_STRING,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "productUri",
#endif
.namespaceZero = true,
.padding = offsetof(UA_ApplicationDescription, productUri) - offsetof(UA_ApplicationDescription, applicationUri) - sizeof(UA_String),
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_LOCALIZEDTEXT,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "applicationName",
#endif
.namespaceZero = true,
.padding = offsetof(UA_ApplicationDescription, applicationName) - offsetof(UA_ApplicationDescription, productUri) - sizeof(UA_String),
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_APPLICATIONTYPE,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "applicationType",
#endif
.namespaceZero = true,
.padding = offsetof(UA_ApplicationDescription, applicationType) - offsetof(UA_ApplicationDescription, applicationName) - sizeof(UA_LocalizedText),
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_STRING,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "gatewayServerUri",
#endif
.namespaceZero = true,
.padding = offsetof(UA_ApplicationDescription, gatewayServerUri) - offsetof(UA_ApplicationDescription, applicationType) - sizeof(UA_ApplicationType),
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_STRING,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "discoveryProfileUri",
#endif
.namespaceZero = true,
.padding = offsetof(UA_ApplicationDescription, discoveryProfileUri) - offsetof(UA_ApplicationDescription, gatewayServerUri) - sizeof(UA_String),
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_STRING,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "discoveryUrls",
#endif
.namespaceZero = true,
.padding = offsetof(UA_ApplicationDescription, discoveryUrlsSize) - offsetof(UA_ApplicationDescription, discoveryProfileUri) - sizeof(UA_String),
.isArray = true
},};
/* NodeTypeDescription */
static UA_DataTypeMember NodeTypeDescription_members[3] = {
{ .memberTypeIndex = UA_TYPES_EXPANDEDNODEID,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "typeDefinitionNode",
#endif
.namespaceZero = true,
.padding = 0,
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_BOOLEAN,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "includeSubTypes",
#endif
.namespaceZero = true,
.padding = offsetof(UA_NodeTypeDescription, includeSubTypes) - offsetof(UA_NodeTypeDescription, typeDefinitionNode) - sizeof(UA_ExpandedNodeId),
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_QUERYDATADESCRIPTION,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "dataToReturn",
#endif
.namespaceZero = true,
.padding = offsetof(UA_NodeTypeDescription, dataToReturnSize) - offsetof(UA_NodeTypeDescription, includeSubTypes) - sizeof(UA_Boolean),
.isArray = true
},};
/* FindServersResponse */
static UA_DataTypeMember FindServersResponse_members[2] = {
{ .memberTypeIndex = UA_TYPES_RESPONSEHEADER,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "responseHeader",
#endif
.namespaceZero = true,
.padding = 0,
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_APPLICATIONDESCRIPTION,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "servers",
#endif
.namespaceZero = true,
.padding = offsetof(UA_FindServersResponse, serversSize) - offsetof(UA_FindServersResponse, responseHeader) - sizeof(UA_ResponseHeader),
.isArray = true
},};
/* ServerStatusDataType */
static UA_DataTypeMember ServerStatusDataType_members[6] = {
{ .memberTypeIndex = UA_TYPES_DATETIME,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "startTime",
#endif
.namespaceZero = true,
.padding = 0,
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_DATETIME,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "currentTime",
#endif
.namespaceZero = true,
.padding = offsetof(UA_ServerStatusDataType, currentTime) - offsetof(UA_ServerStatusDataType, startTime) - sizeof(UA_DateTime),
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_SERVERSTATE,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "state",
#endif
.namespaceZero = true,
.padding = offsetof(UA_ServerStatusDataType, state) - offsetof(UA_ServerStatusDataType, currentTime) - sizeof(UA_DateTime),
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_BUILDINFO,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "buildInfo",
#endif
.namespaceZero = true,
.padding = offsetof(UA_ServerStatusDataType, buildInfo) - offsetof(UA_ServerStatusDataType, state) - sizeof(UA_ServerState),
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_UINT32,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "secondsTillShutdown",
#endif
.namespaceZero = true,
.padding = offsetof(UA_ServerStatusDataType, secondsTillShutdown) - offsetof(UA_ServerStatusDataType, buildInfo) - sizeof(UA_BuildInfo),
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_LOCALIZEDTEXT,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "shutdownReason",
#endif
.namespaceZero = true,
.padding = offsetof(UA_ServerStatusDataType, shutdownReason) - offsetof(UA_ServerStatusDataType, secondsTillShutdown) - sizeof(UA_UInt32),
.isArray = false
},};
/* AddReferencesResponse */
static UA_DataTypeMember AddReferencesResponse_members[3] = {
{ .memberTypeIndex = UA_TYPES_RESPONSEHEADER,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "responseHeader",
#endif
.namespaceZero = true,
.padding = 0,
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_STATUSCODE,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "results",
#endif
.namespaceZero = true,
.padding = offsetof(UA_AddReferencesResponse, resultsSize) - offsetof(UA_AddReferencesResponse, responseHeader) - sizeof(UA_ResponseHeader),
.isArray = true
},
{ .memberTypeIndex = UA_TYPES_DIAGNOSTICINFO,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "diagnosticInfos",
#endif
.namespaceZero = true,
.padding = offsetof(UA_AddReferencesResponse, diagnosticInfosSize) - offsetof(UA_AddReferencesResponse, results) - sizeof(void*),
.isArray = true
},};
/* TranslateBrowsePathsToNodeIdsResponse */
static UA_DataTypeMember TranslateBrowsePathsToNodeIdsResponse_members[3] = {
{ .memberTypeIndex = UA_TYPES_RESPONSEHEADER,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "responseHeader",
#endif
.namespaceZero = true,
.padding = 0,
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_BROWSEPATHRESULT,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "results",
#endif
.namespaceZero = true,
.padding = offsetof(UA_TranslateBrowsePathsToNodeIdsResponse, resultsSize) - offsetof(UA_TranslateBrowsePathsToNodeIdsResponse, responseHeader) - sizeof(UA_ResponseHeader),
.isArray = true
},
{ .memberTypeIndex = UA_TYPES_DIAGNOSTICINFO,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "diagnosticInfos",
#endif
.namespaceZero = true,
.padding = offsetof(UA_TranslateBrowsePathsToNodeIdsResponse, diagnosticInfosSize) - offsetof(UA_TranslateBrowsePathsToNodeIdsResponse, results) - sizeof(void*),
.isArray = true
},};
/* ContentFilterElement */
static UA_DataTypeMember ContentFilterElement_members[2] = {
{ .memberTypeIndex = UA_TYPES_FILTEROPERATOR,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "filterOperator",
#endif
.namespaceZero = true,
.padding = 0,
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_EXTENSIONOBJECT,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "filterOperands",
#endif
.namespaceZero = true,
.padding = offsetof(UA_ContentFilterElement, filterOperandsSize) - offsetof(UA_ContentFilterElement, filterOperator) - sizeof(UA_FilterOperator),
.isArray = true
},};
/* TranslateBrowsePathsToNodeIdsRequest */
static UA_DataTypeMember TranslateBrowsePathsToNodeIdsRequest_members[2] = {
{ .memberTypeIndex = UA_TYPES_REQUESTHEADER,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "requestHeader",
#endif
.namespaceZero = true,
.padding = 0,
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_BROWSEPATH,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "browsePaths",
#endif
.namespaceZero = true,
.padding = offsetof(UA_TranslateBrowsePathsToNodeIdsRequest, browsePathsSize) - offsetof(UA_TranslateBrowsePathsToNodeIdsRequest, requestHeader) - sizeof(UA_RequestHeader),
.isArray = true
},};
/* CloseSessionResponse */
static UA_DataTypeMember CloseSessionResponse_members[1] = {
{ .memberTypeIndex = UA_TYPES_RESPONSEHEADER,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "responseHeader",
#endif
.namespaceZero = true,
.padding = 0,
.isArray = false
},};
/* ServiceFault */
static UA_DataTypeMember ServiceFault_members[1] = {
{ .memberTypeIndex = UA_TYPES_RESPONSEHEADER,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "responseHeader",
#endif
.namespaceZero = true,
.padding = 0,
.isArray = false
},};
/* CreateMonitoredItemsRequest */
static UA_DataTypeMember CreateMonitoredItemsRequest_members[4] = {
{ .memberTypeIndex = UA_TYPES_REQUESTHEADER,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "requestHeader",
#endif
.namespaceZero = true,
.padding = 0,
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_UINT32,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "subscriptionId",
#endif
.namespaceZero = true,
.padding = offsetof(UA_CreateMonitoredItemsRequest, subscriptionId) - offsetof(UA_CreateMonitoredItemsRequest, requestHeader) - sizeof(UA_RequestHeader),
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_TIMESTAMPSTORETURN,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "timestampsToReturn",
#endif
.namespaceZero = true,
.padding = offsetof(UA_CreateMonitoredItemsRequest, timestampsToReturn) - offsetof(UA_CreateMonitoredItemsRequest, subscriptionId) - sizeof(UA_UInt32),
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_MONITOREDITEMCREATEREQUEST,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "itemsToCreate",
#endif
.namespaceZero = true,
.padding = offsetof(UA_CreateMonitoredItemsRequest, itemsToCreateSize) - offsetof(UA_CreateMonitoredItemsRequest, timestampsToReturn) - sizeof(UA_TimestampsToReturn),
.isArray = true
},};
/* ContentFilter */
static UA_DataTypeMember ContentFilter_members[1] = {
{ .memberTypeIndex = UA_TYPES_CONTENTFILTERELEMENT,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "elements",
#endif
.namespaceZero = true,
.padding = 0,
.isArray = true
},};
/* QueryFirstResponse */
static UA_DataTypeMember QueryFirstResponse_members[6] = {
{ .memberTypeIndex = UA_TYPES_RESPONSEHEADER,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "responseHeader",
#endif
.namespaceZero = true,
.padding = 0,
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_QUERYDATASET,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "queryDataSets",
#endif
.namespaceZero = true,
.padding = offsetof(UA_QueryFirstResponse, queryDataSetsSize) - offsetof(UA_QueryFirstResponse, responseHeader) - sizeof(UA_ResponseHeader),
.isArray = true
},
{ .memberTypeIndex = UA_TYPES_BYTESTRING,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "continuationPoint",
#endif
.namespaceZero = true,
.padding = offsetof(UA_QueryFirstResponse, continuationPoint) - offsetof(UA_QueryFirstResponse, queryDataSets) - sizeof(void*),
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_PARSINGRESULT,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "parsingResults",
#endif
.namespaceZero = true,
.padding = offsetof(UA_QueryFirstResponse, parsingResultsSize) - offsetof(UA_QueryFirstResponse, continuationPoint) - sizeof(UA_ByteString),
.isArray = true
},
{ .memberTypeIndex = UA_TYPES_DIAGNOSTICINFO,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "diagnosticInfos",
#endif
.namespaceZero = true,
.padding = offsetof(UA_QueryFirstResponse, diagnosticInfosSize) - offsetof(UA_QueryFirstResponse, parsingResults) - sizeof(void*),
.isArray = true
},
{ .memberTypeIndex = UA_TYPES_CONTENTFILTERRESULT,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "filterResult",
#endif
.namespaceZero = true,
.padding = offsetof(UA_QueryFirstResponse, filterResult) - offsetof(UA_QueryFirstResponse, diagnosticInfos) - sizeof(void*),
.isArray = false
},};
/* AddNodesRequest */
static UA_DataTypeMember AddNodesRequest_members[2] = {
{ .memberTypeIndex = UA_TYPES_REQUESTHEADER,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "requestHeader",
#endif
.namespaceZero = true,
.padding = 0,
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_ADDNODESITEM,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "nodesToAdd",
#endif
.namespaceZero = true,
.padding = offsetof(UA_AddNodesRequest, nodesToAddSize) - offsetof(UA_AddNodesRequest, requestHeader) - sizeof(UA_RequestHeader),
.isArray = true
},};
/* BrowseRequest */
static UA_DataTypeMember BrowseRequest_members[4] = {
{ .memberTypeIndex = UA_TYPES_REQUESTHEADER,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "requestHeader",
#endif
.namespaceZero = true,
.padding = 0,
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_VIEWDESCRIPTION,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "view",
#endif
.namespaceZero = true,
.padding = offsetof(UA_BrowseRequest, view) - offsetof(UA_BrowseRequest, requestHeader) - sizeof(UA_RequestHeader),
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_UINT32,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "requestedMaxReferencesPerNode",
#endif
.namespaceZero = true,
.padding = offsetof(UA_BrowseRequest, requestedMaxReferencesPerNode) - offsetof(UA_BrowseRequest, view) - sizeof(UA_ViewDescription),
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_BROWSEDESCRIPTION,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "nodesToBrowse",
#endif
.namespaceZero = true,
.padding = offsetof(UA_BrowseRequest, nodesToBrowseSize) - offsetof(UA_BrowseRequest, requestedMaxReferencesPerNode) - sizeof(UA_UInt32),
.isArray = true
},};
/* BrowseResult */
static UA_DataTypeMember BrowseResult_members[3] = {
{ .memberTypeIndex = UA_TYPES_STATUSCODE,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "statusCode",
#endif
.namespaceZero = true,
.padding = 0,
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_BYTESTRING,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "continuationPoint",
#endif
.namespaceZero = true,
.padding = offsetof(UA_BrowseResult, continuationPoint) - offsetof(UA_BrowseResult, statusCode) - sizeof(UA_StatusCode),
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_REFERENCEDESCRIPTION,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "references",
#endif
.namespaceZero = true,
.padding = offsetof(UA_BrowseResult, referencesSize) - offsetof(UA_BrowseResult, continuationPoint) - sizeof(UA_ByteString),
.isArray = true
},};
/* CreateSessionRequest */
static UA_DataTypeMember CreateSessionRequest_members[9] = {
{ .memberTypeIndex = UA_TYPES_REQUESTHEADER,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "requestHeader",
#endif
.namespaceZero = true,
.padding = 0,
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_APPLICATIONDESCRIPTION,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "clientDescription",
#endif
.namespaceZero = true,
.padding = offsetof(UA_CreateSessionRequest, clientDescription) - offsetof(UA_CreateSessionRequest, requestHeader) - sizeof(UA_RequestHeader),
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_STRING,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "serverUri",
#endif
.namespaceZero = true,
.padding = offsetof(UA_CreateSessionRequest, serverUri) - offsetof(UA_CreateSessionRequest, clientDescription) - sizeof(UA_ApplicationDescription),
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_STRING,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "endpointUrl",
#endif
.namespaceZero = true,
.padding = offsetof(UA_CreateSessionRequest, endpointUrl) - offsetof(UA_CreateSessionRequest, serverUri) - sizeof(UA_String),
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_STRING,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "sessionName",
#endif
.namespaceZero = true,
.padding = offsetof(UA_CreateSessionRequest, sessionName) - offsetof(UA_CreateSessionRequest, endpointUrl) - sizeof(UA_String),
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_BYTESTRING,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "clientNonce",
#endif
.namespaceZero = true,
.padding = offsetof(UA_CreateSessionRequest, clientNonce) - offsetof(UA_CreateSessionRequest, sessionName) - sizeof(UA_String),
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_BYTESTRING,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "clientCertificate",
#endif
.namespaceZero = true,
.padding = offsetof(UA_CreateSessionRequest, clientCertificate) - offsetof(UA_CreateSessionRequest, clientNonce) - sizeof(UA_ByteString),
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_DOUBLE,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "requestedSessionTimeout",
#endif
.namespaceZero = true,
.padding = offsetof(UA_CreateSessionRequest, requestedSessionTimeout) - offsetof(UA_CreateSessionRequest, clientCertificate) - sizeof(UA_ByteString),
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_UINT32,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "maxResponseMessageSize",
#endif
.namespaceZero = true,
.padding = offsetof(UA_CreateSessionRequest, maxResponseMessageSize) - offsetof(UA_CreateSessionRequest, requestedSessionTimeout) - sizeof(UA_Double),
.isArray = false
},};
/* EndpointDescription */
static UA_DataTypeMember EndpointDescription_members[8] = {
{ .memberTypeIndex = UA_TYPES_STRING,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "endpointUrl",
#endif
.namespaceZero = true,
.padding = 0,
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_APPLICATIONDESCRIPTION,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "server",
#endif
.namespaceZero = true,
.padding = offsetof(UA_EndpointDescription, server) - offsetof(UA_EndpointDescription, endpointUrl) - sizeof(UA_String),
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_BYTESTRING,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "serverCertificate",
#endif
.namespaceZero = true,
.padding = offsetof(UA_EndpointDescription, serverCertificate) - offsetof(UA_EndpointDescription, server) - sizeof(UA_ApplicationDescription),
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_MESSAGESECURITYMODE,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "securityMode",
#endif
.namespaceZero = true,
.padding = offsetof(UA_EndpointDescription, securityMode) - offsetof(UA_EndpointDescription, serverCertificate) - sizeof(UA_ByteString),
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_STRING,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "securityPolicyUri",
#endif
.namespaceZero = true,
.padding = offsetof(UA_EndpointDescription, securityPolicyUri) - offsetof(UA_EndpointDescription, securityMode) - sizeof(UA_MessageSecurityMode),
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_USERTOKENPOLICY,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "userIdentityTokens",
#endif
.namespaceZero = true,
.padding = offsetof(UA_EndpointDescription, userIdentityTokensSize) - offsetof(UA_EndpointDescription, securityPolicyUri) - sizeof(UA_String),
.isArray = true
},
{ .memberTypeIndex = UA_TYPES_STRING,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "transportProfileUri",
#endif
.namespaceZero = true,
.padding = offsetof(UA_EndpointDescription, transportProfileUri) - offsetof(UA_EndpointDescription, userIdentityTokens) - sizeof(void*),
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_BYTE,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "securityLevel",
#endif
.namespaceZero = true,
.padding = offsetof(UA_EndpointDescription, securityLevel) - offsetof(UA_EndpointDescription, transportProfileUri) - sizeof(UA_String),
.isArray = false
},};
/* GetEndpointsResponse */
static UA_DataTypeMember GetEndpointsResponse_members[2] = {
{ .memberTypeIndex = UA_TYPES_RESPONSEHEADER,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "responseHeader",
#endif
.namespaceZero = true,
.padding = 0,
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_ENDPOINTDESCRIPTION,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "endpoints",
#endif
.namespaceZero = true,
.padding = offsetof(UA_GetEndpointsResponse, endpointsSize) - offsetof(UA_GetEndpointsResponse, responseHeader) - sizeof(UA_ResponseHeader),
.isArray = true
},};
/* BrowseNextResponse */
static UA_DataTypeMember BrowseNextResponse_members[3] = {
{ .memberTypeIndex = UA_TYPES_RESPONSEHEADER,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "responseHeader",
#endif
.namespaceZero = true,
.padding = 0,
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_BROWSERESULT,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "results",
#endif
.namespaceZero = true,
.padding = offsetof(UA_BrowseNextResponse, resultsSize) - offsetof(UA_BrowseNextResponse, responseHeader) - sizeof(UA_ResponseHeader),
.isArray = true
},
{ .memberTypeIndex = UA_TYPES_DIAGNOSTICINFO,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "diagnosticInfos",
#endif
.namespaceZero = true,
.padding = offsetof(UA_BrowseNextResponse, diagnosticInfosSize) - offsetof(UA_BrowseNextResponse, results) - sizeof(void*),
.isArray = true
},};
/* BrowseResponse */
static UA_DataTypeMember BrowseResponse_members[3] = {
{ .memberTypeIndex = UA_TYPES_RESPONSEHEADER,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "responseHeader",
#endif
.namespaceZero = true,
.padding = 0,
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_BROWSERESULT,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "results",
#endif
.namespaceZero = true,
.padding = offsetof(UA_BrowseResponse, resultsSize) - offsetof(UA_BrowseResponse, responseHeader) - sizeof(UA_ResponseHeader),
.isArray = true
},
{ .memberTypeIndex = UA_TYPES_DIAGNOSTICINFO,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "diagnosticInfos",
#endif
.namespaceZero = true,
.padding = offsetof(UA_BrowseResponse, diagnosticInfosSize) - offsetof(UA_BrowseResponse, results) - sizeof(void*),
.isArray = true
},};
/* CreateSessionResponse */
static UA_DataTypeMember CreateSessionResponse_members[10] = {
{ .memberTypeIndex = UA_TYPES_RESPONSEHEADER,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "responseHeader",
#endif
.namespaceZero = true,
.padding = 0,
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_NODEID,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "sessionId",
#endif
.namespaceZero = true,
.padding = offsetof(UA_CreateSessionResponse, sessionId) - offsetof(UA_CreateSessionResponse, responseHeader) - sizeof(UA_ResponseHeader),
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_NODEID,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "authenticationToken",
#endif
.namespaceZero = true,
.padding = offsetof(UA_CreateSessionResponse, authenticationToken) - offsetof(UA_CreateSessionResponse, sessionId) - sizeof(UA_NodeId),
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_DOUBLE,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "revisedSessionTimeout",
#endif
.namespaceZero = true,
.padding = offsetof(UA_CreateSessionResponse, revisedSessionTimeout) - offsetof(UA_CreateSessionResponse, authenticationToken) - sizeof(UA_NodeId),
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_BYTESTRING,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "serverNonce",
#endif
.namespaceZero = true,
.padding = offsetof(UA_CreateSessionResponse, serverNonce) - offsetof(UA_CreateSessionResponse, revisedSessionTimeout) - sizeof(UA_Double),
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_BYTESTRING,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "serverCertificate",
#endif
.namespaceZero = true,
.padding = offsetof(UA_CreateSessionResponse, serverCertificate) - offsetof(UA_CreateSessionResponse, serverNonce) - sizeof(UA_ByteString),
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_ENDPOINTDESCRIPTION,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "serverEndpoints",
#endif
.namespaceZero = true,
.padding = offsetof(UA_CreateSessionResponse, serverEndpointsSize) - offsetof(UA_CreateSessionResponse, serverCertificate) - sizeof(UA_ByteString),
.isArray = true
},
{ .memberTypeIndex = UA_TYPES_SIGNEDSOFTWARECERTIFICATE,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "serverSoftwareCertificates",
#endif
.namespaceZero = true,
.padding = offsetof(UA_CreateSessionResponse, serverSoftwareCertificatesSize) - offsetof(UA_CreateSessionResponse, serverEndpoints) - sizeof(void*),
.isArray = true
},
{ .memberTypeIndex = UA_TYPES_SIGNATUREDATA,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "serverSignature",
#endif
.namespaceZero = true,
.padding = offsetof(UA_CreateSessionResponse, serverSignature) - offsetof(UA_CreateSessionResponse, serverSoftwareCertificates) - sizeof(void*),
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_UINT32,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "maxRequestMessageSize",
#endif
.namespaceZero = true,
.padding = offsetof(UA_CreateSessionResponse, maxRequestMessageSize) - offsetof(UA_CreateSessionResponse, serverSignature) - sizeof(UA_SignatureData),
.isArray = false
},};
/* QueryFirstRequest */
static UA_DataTypeMember QueryFirstRequest_members[6] = {
{ .memberTypeIndex = UA_TYPES_REQUESTHEADER,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "requestHeader",
#endif
.namespaceZero = true,
.padding = 0,
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_VIEWDESCRIPTION,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "view",
#endif
.namespaceZero = true,
.padding = offsetof(UA_QueryFirstRequest, view) - offsetof(UA_QueryFirstRequest, requestHeader) - sizeof(UA_RequestHeader),
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_NODETYPEDESCRIPTION,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "nodeTypes",
#endif
.namespaceZero = true,
.padding = offsetof(UA_QueryFirstRequest, nodeTypesSize) - offsetof(UA_QueryFirstRequest, view) - sizeof(UA_ViewDescription),
.isArray = true
},
{ .memberTypeIndex = UA_TYPES_CONTENTFILTER,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "filter",
#endif
.namespaceZero = true,
.padding = offsetof(UA_QueryFirstRequest, filter) - offsetof(UA_QueryFirstRequest, nodeTypes) - sizeof(void*),
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_UINT32,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "maxDataSetsToReturn",
#endif
.namespaceZero = true,
.padding = offsetof(UA_QueryFirstRequest, maxDataSetsToReturn) - offsetof(UA_QueryFirstRequest, filter) - sizeof(UA_ContentFilter),
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_UINT32,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "maxReferencesToReturn",
#endif
.namespaceZero = true,
.padding = offsetof(UA_QueryFirstRequest, maxReferencesToReturn) - offsetof(UA_QueryFirstRequest, maxDataSetsToReturn) - sizeof(UA_UInt32),
.isArray = false
},};
const UA_DataType UA_TYPES[UA_TYPES_COUNT] = {
/* Boolean */
{ .typeId = {.namespaceIndex = 0, .identifierType = UA_NODEIDTYPE_NUMERIC, .identifier.numeric = 1},
.typeIndex = UA_TYPES_BOOLEAN,
#ifdef UA_ENABLE_TYPENAMES
.typeName = "Boolean",
#endif
.memSize = sizeof(UA_Boolean),
.builtin = true,
.fixedSize = true,
.overlayable = true,
.membersSize = 1,
.members = Boolean_members },
/* SByte */
{ .typeId = {.namespaceIndex = 0, .identifierType = UA_NODEIDTYPE_NUMERIC, .identifier.numeric = 2},
.typeIndex = UA_TYPES_SBYTE,
#ifdef UA_ENABLE_TYPENAMES
.typeName = "SByte",
#endif
.memSize = sizeof(UA_SByte),
.builtin = true,
.fixedSize = true,
.overlayable = true,
.membersSize = 1,
.members = SByte_members },
/* Byte */
{ .typeId = {.namespaceIndex = 0, .identifierType = UA_NODEIDTYPE_NUMERIC, .identifier.numeric = 3},
.typeIndex = UA_TYPES_BYTE,
#ifdef UA_ENABLE_TYPENAMES
.typeName = "Byte",
#endif
.memSize = sizeof(UA_Byte),
.builtin = true,
.fixedSize = true,
.overlayable = true,
.membersSize = 1,
.members = Byte_members },
/* Int16 */
{ .typeId = {.namespaceIndex = 0, .identifierType = UA_NODEIDTYPE_NUMERIC, .identifier.numeric = 4},
.typeIndex = UA_TYPES_INT16,
#ifdef UA_ENABLE_TYPENAMES
.typeName = "Int16",
#endif
.memSize = sizeof(UA_Int16),
.builtin = true,
.fixedSize = true,
.overlayable = UA_BINARY_OVERLAYABLE_INTEGER,
.membersSize = 1,
.members = Int16_members },
/* UInt16 */
{ .typeId = {.namespaceIndex = 0, .identifierType = UA_NODEIDTYPE_NUMERIC, .identifier.numeric = 5},
.typeIndex = UA_TYPES_UINT16,
#ifdef UA_ENABLE_TYPENAMES
.typeName = "UInt16",
#endif
.memSize = sizeof(UA_UInt16),
.builtin = true,
.fixedSize = true,
.overlayable = UA_BINARY_OVERLAYABLE_INTEGER,
.membersSize = 1,
.members = UInt16_members },
/* Int32 */
{ .typeId = {.namespaceIndex = 0, .identifierType = UA_NODEIDTYPE_NUMERIC, .identifier.numeric = 6},
.typeIndex = UA_TYPES_INT32,
#ifdef UA_ENABLE_TYPENAMES
.typeName = "Int32",
#endif
.memSize = sizeof(UA_Int32),
.builtin = true,
.fixedSize = true,
.overlayable = UA_BINARY_OVERLAYABLE_INTEGER,
.membersSize = 1,
.members = Int32_members },
/* UInt32 */
{ .typeId = {.namespaceIndex = 0, .identifierType = UA_NODEIDTYPE_NUMERIC, .identifier.numeric = 7},
.typeIndex = UA_TYPES_UINT32,
#ifdef UA_ENABLE_TYPENAMES
.typeName = "UInt32",
#endif
.memSize = sizeof(UA_UInt32),
.builtin = true,
.fixedSize = true,
.overlayable = UA_BINARY_OVERLAYABLE_INTEGER,
.membersSize = 1,
.members = UInt32_members },
/* Int64 */
{ .typeId = {.namespaceIndex = 0, .identifierType = UA_NODEIDTYPE_NUMERIC, .identifier.numeric = 8},
.typeIndex = UA_TYPES_INT64,
#ifdef UA_ENABLE_TYPENAMES
.typeName = "Int64",
#endif
.memSize = sizeof(UA_Int64),
.builtin = true,
.fixedSize = true,
.overlayable = UA_BINARY_OVERLAYABLE_INTEGER,
.membersSize = 1,
.members = Int64_members },
/* UInt64 */
{ .typeId = {.namespaceIndex = 0, .identifierType = UA_NODEIDTYPE_NUMERIC, .identifier.numeric = 9},
.typeIndex = UA_TYPES_UINT64,
#ifdef UA_ENABLE_TYPENAMES
.typeName = "UInt64",
#endif
.memSize = sizeof(UA_UInt64),
.builtin = true,
.fixedSize = true,
.overlayable = UA_BINARY_OVERLAYABLE_INTEGER,
.membersSize = 1,
.members = UInt64_members },
/* Float */
{ .typeId = {.namespaceIndex = 0, .identifierType = UA_NODEIDTYPE_NUMERIC, .identifier.numeric = 10},
.typeIndex = UA_TYPES_FLOAT,
#ifdef UA_ENABLE_TYPENAMES
.typeName = "Float",
#endif
.memSize = sizeof(UA_Float),
.builtin = true,
.fixedSize = true,
.overlayable = UA_BINARY_OVERLAYABLE_FLOAT,
.membersSize = 1,
.members = Float_members },
/* Double */
{ .typeId = {.namespaceIndex = 0, .identifierType = UA_NODEIDTYPE_NUMERIC, .identifier.numeric = 11},
.typeIndex = UA_TYPES_DOUBLE,
#ifdef UA_ENABLE_TYPENAMES
.typeName = "Double",
#endif
.memSize = sizeof(UA_Double),
.builtin = true,
.fixedSize = true,
.overlayable = UA_BINARY_OVERLAYABLE_FLOAT,
.membersSize = 1,
.members = Double_members },
/* String */
{ .typeId = {.namespaceIndex = 0, .identifierType = UA_NODEIDTYPE_NUMERIC, .identifier.numeric = 12},
.typeIndex = UA_TYPES_STRING,
#ifdef UA_ENABLE_TYPENAMES
.typeName = "String",
#endif
.memSize = sizeof(UA_String),
.builtin = true,
.fixedSize = false,
.overlayable = false,
.membersSize = 1,
.members = String_members },
/* DateTime */
{ .typeId = {.namespaceIndex = 0, .identifierType = UA_NODEIDTYPE_NUMERIC, .identifier.numeric = 13},
.typeIndex = UA_TYPES_DATETIME,
#ifdef UA_ENABLE_TYPENAMES
.typeName = "DateTime",
#endif
.memSize = sizeof(UA_DateTime),
.builtin = true,
.fixedSize = true,
.overlayable = UA_BINARY_OVERLAYABLE_INTEGER,
.membersSize = 1,
.members = DateTime_members },
/* Guid */
{ .typeId = {.namespaceIndex = 0, .identifierType = UA_NODEIDTYPE_NUMERIC, .identifier.numeric = 14},
.typeIndex = UA_TYPES_GUID,
#ifdef UA_ENABLE_TYPENAMES
.typeName = "Guid",
#endif
.memSize = sizeof(UA_Guid),
.builtin = true,
.fixedSize = true,
.overlayable = (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))),
.membersSize = 1,
.members = Guid_members },
/* ByteString */
{ .typeId = {.namespaceIndex = 0, .identifierType = UA_NODEIDTYPE_NUMERIC, .identifier.numeric = 15},
.typeIndex = UA_TYPES_BYTESTRING,
#ifdef UA_ENABLE_TYPENAMES
.typeName = "ByteString",
#endif
.memSize = sizeof(UA_ByteString),
.builtin = true,
.fixedSize = false,
.overlayable = false,
.membersSize = 1,
.members = ByteString_members },
/* XmlElement */
{ .typeId = {.namespaceIndex = 0, .identifierType = UA_NODEIDTYPE_NUMERIC, .identifier.numeric = 16},
.typeIndex = UA_TYPES_XMLELEMENT,
#ifdef UA_ENABLE_TYPENAMES
.typeName = "XmlElement",
#endif
.memSize = sizeof(UA_XmlElement),
.builtin = true,
.fixedSize = false,
.overlayable = false,
.membersSize = 1,
.members = XmlElement_members },
/* NodeId */
{ .typeId = {.namespaceIndex = 0, .identifierType = UA_NODEIDTYPE_NUMERIC, .identifier.numeric = 17},
.typeIndex = UA_TYPES_NODEID,
#ifdef UA_ENABLE_TYPENAMES
.typeName = "NodeId",
#endif
.memSize = sizeof(UA_NodeId),
.builtin = true,
.fixedSize = false,
.overlayable = false,
.membersSize = 1,
.members = NodeId_members },
/* ExpandedNodeId */
{ .typeId = {.namespaceIndex = 0, .identifierType = UA_NODEIDTYPE_NUMERIC, .identifier.numeric = 18},
.typeIndex = UA_TYPES_EXPANDEDNODEID,
#ifdef UA_ENABLE_TYPENAMES
.typeName = "ExpandedNodeId",
#endif
.memSize = sizeof(UA_ExpandedNodeId),
.builtin = true,
.fixedSize = false,
.overlayable = false,
.membersSize = 1,
.members = ExpandedNodeId_members },
/* StatusCode */
{ .typeId = {.namespaceIndex = 0, .identifierType = UA_NODEIDTYPE_NUMERIC, .identifier.numeric = 19},
.typeIndex = UA_TYPES_STATUSCODE,
#ifdef UA_ENABLE_TYPENAMES
.typeName = "StatusCode",
#endif
.memSize = sizeof(UA_StatusCode),
.builtin = true,
.fixedSize = true,
.overlayable = UA_BINARY_OVERLAYABLE_INTEGER,
.membersSize = 1,
.members = StatusCode_members },
/* QualifiedName */
{ .typeId = {.namespaceIndex = 0, .identifierType = UA_NODEIDTYPE_NUMERIC, .identifier.numeric = 20},
.typeIndex = UA_TYPES_QUALIFIEDNAME,
#ifdef UA_ENABLE_TYPENAMES
.typeName = "QualifiedName",
#endif
.memSize = sizeof(UA_QualifiedName),
.builtin = true,
.fixedSize = false,
.overlayable = false,
.membersSize = 2,
.members = QualifiedName_members },
/* LocalizedText */
{ .typeId = {.namespaceIndex = 0, .identifierType = UA_NODEIDTYPE_NUMERIC, .identifier.numeric = 21},
.typeIndex = UA_TYPES_LOCALIZEDTEXT,
#ifdef UA_ENABLE_TYPENAMES
.typeName = "LocalizedText",
#endif
.memSize = sizeof(UA_LocalizedText),
.builtin = true,
.fixedSize = false,
.overlayable = false,
.membersSize = 1,
.members = LocalizedText_members },
/* ExtensionObject */
{ .typeId = {.namespaceIndex = 0, .identifierType = UA_NODEIDTYPE_NUMERIC, .identifier.numeric = 22},
.typeIndex = UA_TYPES_EXTENSIONOBJECT,
#ifdef UA_ENABLE_TYPENAMES
.typeName = "ExtensionObject",
#endif
.memSize = sizeof(UA_ExtensionObject),
.builtin = true,
.fixedSize = false,
.overlayable = false,
.membersSize = 1,
.members = ExtensionObject_members },
/* DataValue */
{ .typeId = {.namespaceIndex = 0, .identifierType = UA_NODEIDTYPE_NUMERIC, .identifier.numeric = 23},
.typeIndex = UA_TYPES_DATAVALUE,
#ifdef UA_ENABLE_TYPENAMES
.typeName = "DataValue",
#endif
.memSize = sizeof(UA_DataValue),
.builtin = true,
.fixedSize = false,
.overlayable = false,
.membersSize = 1,
.members = DataValue_members },
/* Variant */
{ .typeId = {.namespaceIndex = 0, .identifierType = UA_NODEIDTYPE_NUMERIC, .identifier.numeric = 24},
.typeIndex = UA_TYPES_VARIANT,
#ifdef UA_ENABLE_TYPENAMES
.typeName = "Variant",
#endif
.memSize = sizeof(UA_Variant),
.builtin = true,
.fixedSize = false,
.overlayable = false,
.membersSize = 1,
.members = Variant_members },
/* DiagnosticInfo */
{ .typeId = {.namespaceIndex = 0, .identifierType = UA_NODEIDTYPE_NUMERIC, .identifier.numeric = 25},
.typeIndex = UA_TYPES_DIAGNOSTICINFO,
#ifdef UA_ENABLE_TYPENAMES
.typeName = "DiagnosticInfo",
#endif
.memSize = sizeof(UA_DiagnosticInfo),
.builtin = true,
.fixedSize = false,
.overlayable = false,
.membersSize = 1,
.members = DiagnosticInfo_members },
/* SignedSoftwareCertificate */
{ .typeId = {.namespaceIndex = 0, .identifierType = UA_NODEIDTYPE_NUMERIC, .identifier.numeric = 344},
.typeIndex = UA_TYPES_SIGNEDSOFTWARECERTIFICATE,
#ifdef UA_ENABLE_TYPENAMES
.typeName = "SignedSoftwareCertificate",
#endif
.memSize = sizeof(UA_SignedSoftwareCertificate),
.builtin = false,
.fixedSize = false,
.overlayable = false,
.membersSize = 2,
.members = SignedSoftwareCertificate_members },
/* BrowsePathTarget */
{ .typeId = {.namespaceIndex = 0, .identifierType = UA_NODEIDTYPE_NUMERIC, .identifier.numeric = 546},
.typeIndex = UA_TYPES_BROWSEPATHTARGET,
#ifdef UA_ENABLE_TYPENAMES
.typeName = "BrowsePathTarget",
#endif
.memSize = sizeof(UA_BrowsePathTarget),
.builtin = false,
.fixedSize = false,
.overlayable = false,
.membersSize = 2,
.members = BrowsePathTarget_members },
/* ViewAttributes */
{ .typeId = {.namespaceIndex = 0, .identifierType = UA_NODEIDTYPE_NUMERIC, .identifier.numeric = 373},
.typeIndex = UA_TYPES_VIEWATTRIBUTES,
#ifdef UA_ENABLE_TYPENAMES
.typeName = "ViewAttributes",
#endif
.memSize = sizeof(UA_ViewAttributes),
.builtin = false,
.fixedSize = false,
.overlayable = false,
.membersSize = 7,
.members = ViewAttributes_members },
/* BrowseResultMask */
{ .typeId = {.namespaceIndex = 0, .identifierType = UA_NODEIDTYPE_NUMERIC, .identifier.numeric = 6},
.typeIndex = UA_TYPES_INT32,
#ifdef UA_ENABLE_TYPENAMES
.typeName = "BrowseResultMask",
#endif
.memSize = sizeof(UA_BrowseResultMask),
.builtin = true,
.fixedSize = true,
.overlayable = UA_BINARY_OVERLAYABLE_INTEGER,
.membersSize = 1,
.members = BrowseResultMask_members },
/* RequestHeader */
{ .typeId = {.namespaceIndex = 0, .identifierType = UA_NODEIDTYPE_NUMERIC, .identifier.numeric = 389},
.typeIndex = UA_TYPES_REQUESTHEADER,
#ifdef UA_ENABLE_TYPENAMES
.typeName = "RequestHeader",
#endif
.memSize = sizeof(UA_RequestHeader),
.builtin = false,
.fixedSize = false,
.overlayable = false,
.membersSize = 7,
.members = RequestHeader_members },
/* MonitoredItemModifyResult */
{ .typeId = {.namespaceIndex = 0, .identifierType = UA_NODEIDTYPE_NUMERIC, .identifier.numeric = 758},
.typeIndex = UA_TYPES_MONITOREDITEMMODIFYRESULT,
#ifdef UA_ENABLE_TYPENAMES
.typeName = "MonitoredItemModifyResult",
#endif
.memSize = sizeof(UA_MonitoredItemModifyResult),
.builtin = false,
.fixedSize = false,
.overlayable = false,
.membersSize = 4,
.members = MonitoredItemModifyResult_members },
/* ViewDescription */
{ .typeId = {.namespaceIndex = 0, .identifierType = UA_NODEIDTYPE_NUMERIC, .identifier.numeric = 511},
.typeIndex = UA_TYPES_VIEWDESCRIPTION,
#ifdef UA_ENABLE_TYPENAMES
.typeName = "ViewDescription",
#endif
.memSize = sizeof(UA_ViewDescription),
.builtin = false,
.fixedSize = false,
.overlayable = false,
.membersSize = 3,
.members = ViewDescription_members },
/* CloseSecureChannelRequest */
{ .typeId = {.namespaceIndex = 0, .identifierType = UA_NODEIDTYPE_NUMERIC, .identifier.numeric = 450},
.typeIndex = UA_TYPES_CLOSESECURECHANNELREQUEST,
#ifdef UA_ENABLE_TYPENAMES
.typeName = "CloseSecureChannelRequest",
#endif
.memSize = sizeof(UA_CloseSecureChannelRequest),
.builtin = false,
.fixedSize = false,
.overlayable = false,
.membersSize = 1,
.members = CloseSecureChannelRequest_members },
/* AddNodesResult */
{ .typeId = {.namespaceIndex = 0, .identifierType = UA_NODEIDTYPE_NUMERIC, .identifier.numeric = 483},
.typeIndex = UA_TYPES_ADDNODESRESULT,
#ifdef UA_ENABLE_TYPENAMES
.typeName = "AddNodesResult",
#endif
.memSize = sizeof(UA_AddNodesResult),
.builtin = false,
.fixedSize = false,
.overlayable = false,
.membersSize = 2,
.members = AddNodesResult_members },
/* VariableAttributes */
{ .typeId = {.namespaceIndex = 0, .identifierType = UA_NODEIDTYPE_NUMERIC, .identifier.numeric = 355},
.typeIndex = UA_TYPES_VARIABLEATTRIBUTES,
#ifdef UA_ENABLE_TYPENAMES
.typeName = "VariableAttributes",
#endif
.memSize = sizeof(UA_VariableAttributes),
.builtin = false,
.fixedSize = false,
.overlayable = false,
.membersSize = 13,
.members = VariableAttributes_members },
/* NotificationMessage */
{ .typeId = {.namespaceIndex = 0, .identifierType = UA_NODEIDTYPE_NUMERIC, .identifier.numeric = 803},
.typeIndex = UA_TYPES_NOTIFICATIONMESSAGE,
#ifdef UA_ENABLE_TYPENAMES
.typeName = "NotificationMessage",
#endif
.memSize = sizeof(UA_NotificationMessage),
.builtin = false,
.fixedSize = false,
.overlayable = false,
.membersSize = 3,
.members = NotificationMessage_members },
/* NodeAttributesMask */
{ .typeId = {.namespaceIndex = 0, .identifierType = UA_NODEIDTYPE_NUMERIC, .identifier.numeric = 6},
.typeIndex = UA_TYPES_INT32,
#ifdef UA_ENABLE_TYPENAMES
.typeName = "NodeAttributesMask",
#endif
.memSize = sizeof(UA_NodeAttributesMask),
.builtin = true,
.fixedSize = true,
.overlayable = UA_BINARY_OVERLAYABLE_INTEGER,
.membersSize = 1,
.members = NodeAttributesMask_members },
/* MonitoringMode */
{ .typeId = {.namespaceIndex = 0, .identifierType = UA_NODEIDTYPE_NUMERIC, .identifier.numeric = 6},
.typeIndex = UA_TYPES_INT32,
#ifdef UA_ENABLE_TYPENAMES
.typeName = "MonitoringMode",
#endif
.memSize = sizeof(UA_MonitoringMode),
.builtin = true,
.fixedSize = true,
.overlayable = UA_BINARY_OVERLAYABLE_INTEGER,
.membersSize = 1,
.members = MonitoringMode_members },
/* CallMethodResult */
{ .typeId = {.namespaceIndex = 0, .identifierType = UA_NODEIDTYPE_NUMERIC, .identifier.numeric = 707},
.typeIndex = UA_TYPES_CALLMETHODRESULT,
#ifdef UA_ENABLE_TYPENAMES
.typeName = "CallMethodResult",
#endif
.memSize = sizeof(UA_CallMethodResult),
.builtin = false,
.fixedSize = false,
.overlayable = false,
.membersSize = 4,
.members = CallMethodResult_members },
/* ParsingResult */
{ .typeId = {.namespaceIndex = 0, .identifierType = UA_NODEIDTYPE_NUMERIC, .identifier.numeric = 610},
.typeIndex = UA_TYPES_PARSINGRESULT,
#ifdef UA_ENABLE_TYPENAMES
.typeName = "ParsingResult",
#endif
.memSize = sizeof(UA_ParsingResult),
.builtin = false,
.fixedSize = false,
.overlayable = false,
.membersSize = 3,
.members = ParsingResult_members },
/* RelativePathElement */
{ .typeId = {.namespaceIndex = 0, .identifierType = UA_NODEIDTYPE_NUMERIC, .identifier.numeric = 537},
.typeIndex = UA_TYPES_RELATIVEPATHELEMENT,
#ifdef UA_ENABLE_TYPENAMES
.typeName = "RelativePathElement",
#endif
.memSize = sizeof(UA_RelativePathElement),
.builtin = false,
.fixedSize = false,
.overlayable = false,
.membersSize = 4,
.members = RelativePathElement_members },
/* BrowseDirection */
{ .typeId = {.namespaceIndex = 0, .identifierType = UA_NODEIDTYPE_NUMERIC, .identifier.numeric = 6},
.typeIndex = UA_TYPES_INT32,
#ifdef UA_ENABLE_TYPENAMES
.typeName = "BrowseDirection",
#endif
.memSize = sizeof(UA_BrowseDirection),
.builtin = true,
.fixedSize = true,
.overlayable = UA_BINARY_OVERLAYABLE_INTEGER,
.membersSize = 1,
.members = BrowseDirection_members },
/* CallMethodRequest */
{ .typeId = {.namespaceIndex = 0, .identifierType = UA_NODEIDTYPE_NUMERIC, .identifier.numeric = 704},
.typeIndex = UA_TYPES_CALLMETHODREQUEST,
#ifdef UA_ENABLE_TYPENAMES
.typeName = "CallMethodRequest",
#endif
.memSize = sizeof(UA_CallMethodRequest),
.builtin = false,
.fixedSize = false,
.overlayable = false,
.membersSize = 3,
.members = CallMethodRequest_members },
/* ServerState */
{ .typeId = {.namespaceIndex = 0, .identifierType = UA_NODEIDTYPE_NUMERIC, .identifier.numeric = 6},
.typeIndex = UA_TYPES_INT32,
#ifdef UA_ENABLE_TYPENAMES
.typeName = "ServerState",
#endif
.memSize = sizeof(UA_ServerState),
.builtin = true,
.fixedSize = true,
.overlayable = UA_BINARY_OVERLAYABLE_INTEGER,
.membersSize = 1,
.members = ServerState_members },
/* UnregisterNodesRequest */
{ .typeId = {.namespaceIndex = 0, .identifierType = UA_NODEIDTYPE_NUMERIC, .identifier.numeric = 564},
.typeIndex = UA_TYPES_UNREGISTERNODESREQUEST,
#ifdef UA_ENABLE_TYPENAMES
.typeName = "UnregisterNodesRequest",
#endif
.memSize = sizeof(UA_UnregisterNodesRequest),
.builtin = false,
.fixedSize = false,
.overlayable = false,
.membersSize = 2,
.members = UnregisterNodesRequest_members },
/* ContentFilterElementResult */
{ .typeId = {.namespaceIndex = 0, .identifierType = UA_NODEIDTYPE_NUMERIC, .identifier.numeric = 604},
.typeIndex = UA_TYPES_CONTENTFILTERELEMENTRESULT,
#ifdef UA_ENABLE_TYPENAMES
.typeName = "ContentFilterElementResult",
#endif
.memSize = sizeof(UA_ContentFilterElementResult),
.builtin = false,
.fixedSize = false,
.overlayable = false,
.membersSize = 3,
.members = ContentFilterElementResult_members },
/* QueryDataSet */
{ .typeId = {.namespaceIndex = 0, .identifierType = UA_NODEIDTYPE_NUMERIC, .identifier.numeric = 577},
.typeIndex = UA_TYPES_QUERYDATASET,
#ifdef UA_ENABLE_TYPENAMES
.typeName = "QueryDataSet",
#endif
.memSize = sizeof(UA_QueryDataSet),
.builtin = false,
.fixedSize = false,
.overlayable = false,
.membersSize = 3,
.members = QueryDataSet_members },
/* SetPublishingModeRequest */
{ .typeId = {.namespaceIndex = 0, .identifierType = UA_NODEIDTYPE_NUMERIC, .identifier.numeric = 797},
.typeIndex = UA_TYPES_SETPUBLISHINGMODEREQUEST,
#ifdef UA_ENABLE_TYPENAMES
.typeName = "SetPublishingModeRequest",
#endif
.memSize = sizeof(UA_SetPublishingModeRequest),
.builtin = false,
.fixedSize = false,
.overlayable = false,
.membersSize = 3,
.members = SetPublishingModeRequest_members },
/* TimestampsToReturn */
{ .typeId = {.namespaceIndex = 0, .identifierType = UA_NODEIDTYPE_NUMERIC, .identifier.numeric = 6},
.typeIndex = UA_TYPES_INT32,
#ifdef UA_ENABLE_TYPENAMES
.typeName = "TimestampsToReturn",
#endif
.memSize = sizeof(UA_TimestampsToReturn),
.builtin = true,
.fixedSize = true,
.overlayable = UA_BINARY_OVERLAYABLE_INTEGER,
.membersSize = 1,
.members = TimestampsToReturn_members },
/* CallRequest */
{ .typeId = {.namespaceIndex = 0, .identifierType = UA_NODEIDTYPE_NUMERIC, .identifier.numeric = 710},
.typeIndex = UA_TYPES_CALLREQUEST,
#ifdef UA_ENABLE_TYPENAMES
.typeName = "CallRequest",
#endif
.memSize = sizeof(UA_CallRequest),
.builtin = false,
.fixedSize = false,
.overlayable = false,
.membersSize = 2,
.members = CallRequest_members },
/* MethodAttributes */
{ .typeId = {.namespaceIndex = 0, .identifierType = UA_NODEIDTYPE_NUMERIC, .identifier.numeric = 358},
.typeIndex = UA_TYPES_METHODATTRIBUTES,
#ifdef UA_ENABLE_TYPENAMES
.typeName = "MethodAttributes",
#endif
.memSize = sizeof(UA_MethodAttributes),
.builtin = false,
.fixedSize = false,
.overlayable = false,
.membersSize = 7,
.members = MethodAttributes_members },
/* DeleteReferencesItem */
{ .typeId = {.namespaceIndex = 0, .identifierType = UA_NODEIDTYPE_NUMERIC, .identifier.numeric = 385},
.typeIndex = UA_TYPES_DELETEREFERENCESITEM,
#ifdef UA_ENABLE_TYPENAMES
.typeName = "DeleteReferencesItem",
#endif
.memSize = sizeof(UA_DeleteReferencesItem),
.builtin = false,
.fixedSize = false,
.overlayable = false,
.membersSize = 5,
.members = DeleteReferencesItem_members },
/* WriteValue */
{ .typeId = {.namespaceIndex = 0, .identifierType = UA_NODEIDTYPE_NUMERIC, .identifier.numeric = 668},
.typeIndex = UA_TYPES_WRITEVALUE,
#ifdef UA_ENABLE_TYPENAMES
.typeName = "WriteValue",
#endif
.memSize = sizeof(UA_WriteValue),
.builtin = false,
.fixedSize = false,
.overlayable = false,
.membersSize = 4,
.members = WriteValue_members },
/* MonitoredItemCreateResult */
{ .typeId = {.namespaceIndex = 0, .identifierType = UA_NODEIDTYPE_NUMERIC, .identifier.numeric = 746},
.typeIndex = UA_TYPES_MONITOREDITEMCREATERESULT,
#ifdef UA_ENABLE_TYPENAMES
.typeName = "MonitoredItemCreateResult",
#endif
.memSize = sizeof(UA_MonitoredItemCreateResult),
.builtin = false,
.fixedSize = false,
.overlayable = false,
.membersSize = 5,
.members = MonitoredItemCreateResult_members },
/* MessageSecurityMode */
{ .typeId = {.namespaceIndex = 0, .identifierType = UA_NODEIDTYPE_NUMERIC, .identifier.numeric = 6},
.typeIndex = UA_TYPES_INT32,
#ifdef UA_ENABLE_TYPENAMES
.typeName = "MessageSecurityMode",
#endif
.memSize = sizeof(UA_MessageSecurityMode),
.builtin = true,
.fixedSize = true,
.overlayable = UA_BINARY_OVERLAYABLE_INTEGER,
.membersSize = 1,
.members = MessageSecurityMode_members },
/* MonitoringParameters */
{ .typeId = {.namespaceIndex = 0, .identifierType = UA_NODEIDTYPE_NUMERIC, .identifier.numeric = 740},
.typeIndex = UA_TYPES_MONITORINGPARAMETERS,
#ifdef UA_ENABLE_TYPENAMES
.typeName = "MonitoringParameters",
#endif
.memSize = sizeof(UA_MonitoringParameters),
.builtin = false,
.fixedSize = false,
.overlayable = false,
.membersSize = 5,
.members = MonitoringParameters_members },
/* SignatureData */
{ .typeId = {.namespaceIndex = 0, .identifierType = UA_NODEIDTYPE_NUMERIC, .identifier.numeric = 456},
.typeIndex = UA_TYPES_SIGNATUREDATA,
#ifdef UA_ENABLE_TYPENAMES
.typeName = "SignatureData",
#endif
.memSize = sizeof(UA_SignatureData),
.builtin = false,
.fixedSize = false,
.overlayable = false,
.membersSize = 2,
.members = SignatureData_members },
/* ReferenceNode */
{ .typeId = {.namespaceIndex = 0, .identifierType = UA_NODEIDTYPE_NUMERIC, .identifier.numeric = 285},
.typeIndex = UA_TYPES_REFERENCENODE,
#ifdef UA_ENABLE_TYPENAMES
.typeName = "ReferenceNode",
#endif
.memSize = sizeof(UA_ReferenceNode),
.builtin = false,
.fixedSize = false,
.overlayable = false,
.membersSize = 3,
.members = ReferenceNode_members },
/* Argument */
{ .typeId = {.namespaceIndex = 0, .identifierType = UA_NODEIDTYPE_NUMERIC, .identifier.numeric = 296},
.typeIndex = UA_TYPES_ARGUMENT,
#ifdef UA_ENABLE_TYPENAMES
.typeName = "Argument",
#endif
.memSize = sizeof(UA_Argument),
.builtin = false,
.fixedSize = false,
.overlayable = false,
.membersSize = 5,
.members = Argument_members },
/* UserIdentityToken */
{ .typeId = {.namespaceIndex = 0, .identifierType = UA_NODEIDTYPE_NUMERIC, .identifier.numeric = 316},
.typeIndex = UA_TYPES_USERIDENTITYTOKEN,
#ifdef UA_ENABLE_TYPENAMES
.typeName = "UserIdentityToken",
#endif
.memSize = sizeof(UA_UserIdentityToken),
.builtin = false,
.fixedSize = false,
.overlayable = false,
.membersSize = 1,
.members = UserIdentityToken_members },
/* ObjectTypeAttributes */
{ .typeId = {.namespaceIndex = 0, .identifierType = UA_NODEIDTYPE_NUMERIC, .identifier.numeric = 361},
.typeIndex = UA_TYPES_OBJECTTYPEATTRIBUTES,
#ifdef UA_ENABLE_TYPENAMES
.typeName = "ObjectTypeAttributes",
#endif
.memSize = sizeof(UA_ObjectTypeAttributes),
.builtin = false,
.fixedSize = false,
.overlayable = false,
.membersSize = 6,
.members = ObjectTypeAttributes_members },
/* SecurityTokenRequestType */
{ .typeId = {.namespaceIndex = 0, .identifierType = UA_NODEIDTYPE_NUMERIC, .identifier.numeric = 6},
.typeIndex = UA_TYPES_INT32,
#ifdef UA_ENABLE_TYPENAMES
.typeName = "SecurityTokenRequestType",
#endif
.memSize = sizeof(UA_SecurityTokenRequestType),
.builtin = true,
.fixedSize = true,
.overlayable = UA_BINARY_OVERLAYABLE_INTEGER,
.membersSize = 1,
.members = SecurityTokenRequestType_members },
/* BuildInfo */
{ .typeId = {.namespaceIndex = 0, .identifierType = UA_NODEIDTYPE_NUMERIC, .identifier.numeric = 338},
.typeIndex = UA_TYPES_BUILDINFO,
#ifdef UA_ENABLE_TYPENAMES
.typeName = "BuildInfo",
#endif
.memSize = sizeof(UA_BuildInfo),
.builtin = false,
.fixedSize = false,
.overlayable = false,
.membersSize = 6,
.members = BuildInfo_members },
/* NodeClass */
{ .typeId = {.namespaceIndex = 0, .identifierType = UA_NODEIDTYPE_NUMERIC, .identifier.numeric = 6},
.typeIndex = UA_TYPES_INT32,
#ifdef UA_ENABLE_TYPENAMES
.typeName = "NodeClass",
#endif
.memSize = sizeof(UA_NodeClass),
.builtin = true,
.fixedSize = true,
.overlayable = UA_BINARY_OVERLAYABLE_INTEGER,
.membersSize = 1,
.members = NodeClass_members },
/* ChannelSecurityToken */
{ .typeId = {.namespaceIndex = 0, .identifierType = UA_NODEIDTYPE_NUMERIC, .identifier.numeric = 441},
.typeIndex = UA_TYPES_CHANNELSECURITYTOKEN,
#ifdef UA_ENABLE_TYPENAMES
.typeName = "ChannelSecurityToken",
#endif
.memSize = sizeof(UA_ChannelSecurityToken),
.builtin = false,
.fixedSize = true,
.overlayable = 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)),
.membersSize = 4,
.members = ChannelSecurityToken_members },
/* MonitoredItemNotification */
{ .typeId = {.namespaceIndex = 0, .identifierType = UA_NODEIDTYPE_NUMERIC, .identifier.numeric = 806},
.typeIndex = UA_TYPES_MONITOREDITEMNOTIFICATION,
#ifdef UA_ENABLE_TYPENAMES
.typeName = "MonitoredItemNotification",
#endif
.memSize = sizeof(UA_MonitoredItemNotification),
.builtin = false,
.fixedSize = false,
.overlayable = false,
.membersSize = 2,
.members = MonitoredItemNotification_members },
/* DeleteNodesItem */
{ .typeId = {.namespaceIndex = 0, .identifierType = UA_NODEIDTYPE_NUMERIC, .identifier.numeric = 382},
.typeIndex = UA_TYPES_DELETENODESITEM,
#ifdef UA_ENABLE_TYPENAMES
.typeName = "DeleteNodesItem",
#endif
.memSize = sizeof(UA_DeleteNodesItem),
.builtin = false,
.fixedSize = false,
.overlayable = false,
.membersSize = 2,
.members = DeleteNodesItem_members },
/* SubscriptionAcknowledgement */
{ .typeId = {.namespaceIndex = 0, .identifierType = UA_NODEIDTYPE_NUMERIC, .identifier.numeric = 821},
.typeIndex = UA_TYPES_SUBSCRIPTIONACKNOWLEDGEMENT,
#ifdef UA_ENABLE_TYPENAMES
.typeName = "SubscriptionAcknowledgement",
#endif
.memSize = sizeof(UA_SubscriptionAcknowledgement),
.builtin = false,
.fixedSize = true,
.overlayable = true && UA_BINARY_OVERLAYABLE_INTEGER && UA_BINARY_OVERLAYABLE_INTEGER && offsetof(UA_SubscriptionAcknowledgement, sequenceNumber) == (offsetof(UA_SubscriptionAcknowledgement, subscriptionId) + sizeof(UA_UInt32)),
.membersSize = 2,
.members = SubscriptionAcknowledgement_members },
/* ReadValueId */
{ .typeId = {.namespaceIndex = 0, .identifierType = UA_NODEIDTYPE_NUMERIC, .identifier.numeric = 626},
.typeIndex = UA_TYPES_READVALUEID,
#ifdef UA_ENABLE_TYPENAMES
.typeName = "ReadValueId",
#endif
.memSize = sizeof(UA_ReadValueId),
.builtin = false,
.fixedSize = false,
.overlayable = false,
.membersSize = 4,
.members = ReadValueId_members },
/* AnonymousIdentityToken */
{ .typeId = {.namespaceIndex = 0, .identifierType = UA_NODEIDTYPE_NUMERIC, .identifier.numeric = 319},
.typeIndex = UA_TYPES_ANONYMOUSIDENTITYTOKEN,
#ifdef UA_ENABLE_TYPENAMES
.typeName = "AnonymousIdentityToken",
#endif
.memSize = sizeof(UA_AnonymousIdentityToken),
.builtin = false,
.fixedSize = false,
.overlayable = false,
.membersSize = 1,
.members = AnonymousIdentityToken_members },
/* DataTypeAttributes */
{ .typeId = {.namespaceIndex = 0, .identifierType = UA_NODEIDTYPE_NUMERIC, .identifier.numeric = 370},
.typeIndex = UA_TYPES_DATATYPEATTRIBUTES,
#ifdef UA_ENABLE_TYPENAMES
.typeName = "DataTypeAttributes",
#endif
.memSize = sizeof(UA_DataTypeAttributes),
.builtin = false,
.fixedSize = false,
.overlayable = false,
.membersSize = 6,
.members = DataTypeAttributes_members },
/* ResponseHeader */
{ .typeId = {.namespaceIndex = 0, .identifierType = UA_NODEIDTYPE_NUMERIC, .identifier.numeric = 392},
.typeIndex = UA_TYPES_RESPONSEHEADER,
#ifdef UA_ENABLE_TYPENAMES
.typeName = "ResponseHeader",
#endif
.memSize = sizeof(UA_ResponseHeader),
.builtin = false,
.fixedSize = false,
.overlayable = false,
.membersSize = 6,
.members = ResponseHeader_members },
/* DeleteSubscriptionsRequest */
{ .typeId = {.namespaceIndex = 0, .identifierType = UA_NODEIDTYPE_NUMERIC, .identifier.numeric = 845},
.typeIndex = UA_TYPES_DELETESUBSCRIPTIONSREQUEST,
#ifdef UA_ENABLE_TYPENAMES
.typeName = "DeleteSubscriptionsRequest",
#endif
.memSize = sizeof(UA_DeleteSubscriptionsRequest),
.builtin = false,
.fixedSize = false,
.overlayable = false,
.membersSize = 2,
.members = DeleteSubscriptionsRequest_members },
/* DataChangeNotification */
{ .typeId = {.namespaceIndex = 0, .identifierType = UA_NODEIDTYPE_NUMERIC, .identifier.numeric = 809},
.typeIndex = UA_TYPES_DATACHANGENOTIFICATION,
#ifdef UA_ENABLE_TYPENAMES
.typeName = "DataChangeNotification",
#endif
.memSize = sizeof(UA_DataChangeNotification),
.builtin = false,
.fixedSize = false,
.overlayable = false,
.membersSize = 2,
.members = DataChangeNotification_members },
/* DeleteMonitoredItemsResponse */
{ .typeId = {.namespaceIndex = 0, .identifierType = UA_NODEIDTYPE_NUMERIC, .identifier.numeric = 782},
.typeIndex = UA_TYPES_DELETEMONITOREDITEMSRESPONSE,
#ifdef UA_ENABLE_TYPENAMES
.typeName = "DeleteMonitoredItemsResponse",
#endif
.memSize = sizeof(UA_DeleteMonitoredItemsResponse),
.builtin = false,
.fixedSize = false,
.overlayable = false,
.membersSize = 3,
.members = DeleteMonitoredItemsResponse_members },
/* RelativePath */
{ .typeId = {.namespaceIndex = 0, .identifierType = UA_NODEIDTYPE_NUMERIC, .identifier.numeric = 540},
.typeIndex = UA_TYPES_RELATIVEPATH,
#ifdef UA_ENABLE_TYPENAMES
.typeName = "RelativePath",
#endif
.memSize = sizeof(UA_RelativePath),
.builtin = false,
.fixedSize = false,
.overlayable = false,
.membersSize = 1,
.members = RelativePath_members },
/* RegisterNodesRequest */
{ .typeId = {.namespaceIndex = 0, .identifierType = UA_NODEIDTYPE_NUMERIC, .identifier.numeric = 558},
.typeIndex = UA_TYPES_REGISTERNODESREQUEST,
#ifdef UA_ENABLE_TYPENAMES
.typeName = "RegisterNodesRequest",
#endif
.memSize = sizeof(UA_RegisterNodesRequest),
.builtin = false,
.fixedSize = false,
.overlayable = false,
.membersSize = 2,
.members = RegisterNodesRequest_members },
/* DeleteNodesRequest */
{ .typeId = {.namespaceIndex = 0, .identifierType = UA_NODEIDTYPE_NUMERIC, .identifier.numeric = 498},
.typeIndex = UA_TYPES_DELETENODESREQUEST,
#ifdef UA_ENABLE_TYPENAMES
.typeName = "DeleteNodesRequest",
#endif
.memSize = sizeof(UA_DeleteNodesRequest),
.builtin = false,
.fixedSize = false,
.overlayable = false,
.membersSize = 2,
.members = DeleteNodesRequest_members },
/* PublishResponse */
{ .typeId = {.namespaceIndex = 0, .identifierType = UA_NODEIDTYPE_NUMERIC, .identifier.numeric = 827},
.typeIndex = UA_TYPES_PUBLISHRESPONSE,
#ifdef UA_ENABLE_TYPENAMES
.typeName = "PublishResponse",
#endif
.memSize = sizeof(UA_PublishResponse),
.builtin = false,
.fixedSize = false,
.overlayable = false,
.membersSize = 7,
.members = PublishResponse_members },
/* MonitoredItemModifyRequest */
{ .typeId = {.namespaceIndex = 0, .identifierType = UA_NODEIDTYPE_NUMERIC, .identifier.numeric = 755},
.typeIndex = UA_TYPES_MONITOREDITEMMODIFYREQUEST,
#ifdef UA_ENABLE_TYPENAMES
.typeName = "MonitoredItemModifyRequest",
#endif
.memSize = sizeof(UA_MonitoredItemModifyRequest),
.builtin = false,
.fixedSize = false,
.overlayable = false,
.membersSize = 2,
.members = MonitoredItemModifyRequest_members },
/* UserNameIdentityToken */
{ .typeId = {.namespaceIndex = 0, .identifierType = UA_NODEIDTYPE_NUMERIC, .identifier.numeric = 322},
.typeIndex = UA_TYPES_USERNAMEIDENTITYTOKEN,
#ifdef UA_ENABLE_TYPENAMES
.typeName = "UserNameIdentityToken",
#endif
.memSize = sizeof(UA_UserNameIdentityToken),
.builtin = false,
.fixedSize = false,
.overlayable = false,
.membersSize = 4,
.members = UserNameIdentityToken_members },
/* IdType */
{ .typeId = {.namespaceIndex = 0, .identifierType = UA_NODEIDTYPE_NUMERIC, .identifier.numeric = 6},
.typeIndex = UA_TYPES_INT32,
#ifdef UA_ENABLE_TYPENAMES
.typeName = "IdType",
#endif
.memSize = sizeof(UA_IdType),
.builtin = true,
.fixedSize = true,
.overlayable = UA_BINARY_OVERLAYABLE_INTEGER,
.membersSize = 1,
.members = IdType_members },
/* UserTokenType */
{ .typeId = {.namespaceIndex = 0, .identifierType = UA_NODEIDTYPE_NUMERIC, .identifier.numeric = 6},
.typeIndex = UA_TYPES_INT32,
#ifdef UA_ENABLE_TYPENAMES
.typeName = "UserTokenType",
#endif
.memSize = sizeof(UA_UserTokenType),
.builtin = true,
.fixedSize = true,
.overlayable = UA_BINARY_OVERLAYABLE_INTEGER,
.membersSize = 1,
.members = UserTokenType_members },
/* NodeAttributes */
{ .typeId = {.namespaceIndex = 0, .identifierType = UA_NODEIDTYPE_NUMERIC, .identifier.numeric = 349},
.typeIndex = UA_TYPES_NODEATTRIBUTES,
#ifdef UA_ENABLE_TYPENAMES
.typeName = "NodeAttributes",
#endif
.memSize = sizeof(UA_NodeAttributes),
.builtin = false,
.fixedSize = false,
.overlayable = false,
.membersSize = 5,
.members = NodeAttributes_members },
/* ActivateSessionRequest */
{ .typeId = {.namespaceIndex = 0, .identifierType = UA_NODEIDTYPE_NUMERIC, .identifier.numeric = 465},
.typeIndex = UA_TYPES_ACTIVATESESSIONREQUEST,
#ifdef UA_ENABLE_TYPENAMES
.typeName = "ActivateSessionRequest",
#endif
.memSize = sizeof(UA_ActivateSessionRequest),
.builtin = false,
.fixedSize = false,
.overlayable = false,
.membersSize = 6,
.members = ActivateSessionRequest_members },
/* OpenSecureChannelResponse */
{ .typeId = {.namespaceIndex = 0, .identifierType = UA_NODEIDTYPE_NUMERIC, .identifier.numeric = 447},
.typeIndex = UA_TYPES_OPENSECURECHANNELRESPONSE,
#ifdef UA_ENABLE_TYPENAMES
.typeName = "OpenSecureChannelResponse",
#endif
.memSize = sizeof(UA_OpenSecureChannelResponse),
.builtin = false,
.fixedSize = false,
.overlayable = false,
.membersSize = 4,
.members = OpenSecureChannelResponse_members },
/* ApplicationType */
{ .typeId = {.namespaceIndex = 0, .identifierType = UA_NODEIDTYPE_NUMERIC, .identifier.numeric = 6},
.typeIndex = UA_TYPES_INT32,
#ifdef UA_ENABLE_TYPENAMES
.typeName = "ApplicationType",
#endif
.memSize = sizeof(UA_ApplicationType),
.builtin = true,
.fixedSize = true,
.overlayable = UA_BINARY_OVERLAYABLE_INTEGER,
.membersSize = 1,
.members = ApplicationType_members },
/* QueryNextResponse */
{ .typeId = {.namespaceIndex = 0, .identifierType = UA_NODEIDTYPE_NUMERIC, .identifier.numeric = 622},
.typeIndex = UA_TYPES_QUERYNEXTRESPONSE,
#ifdef UA_ENABLE_TYPENAMES
.typeName = "QueryNextResponse",
#endif
.memSize = sizeof(UA_QueryNextResponse),
.builtin = false,
.fixedSize = false,
.overlayable = false,
.membersSize = 3,
.members = QueryNextResponse_members },
/* ActivateSessionResponse */
{ .typeId = {.namespaceIndex = 0, .identifierType = UA_NODEIDTYPE_NUMERIC, .identifier.numeric = 468},
.typeIndex = UA_TYPES_ACTIVATESESSIONRESPONSE,
#ifdef UA_ENABLE_TYPENAMES
.typeName = "ActivateSessionResponse",
#endif
.memSize = sizeof(UA_ActivateSessionResponse),
.builtin = false,
.fixedSize = false,
.overlayable = false,
.membersSize = 4,
.members = ActivateSessionResponse_members },
/* FilterOperator */
{ .typeId = {.namespaceIndex = 0, .identifierType = UA_NODEIDTYPE_NUMERIC, .identifier.numeric = 6},
.typeIndex = UA_TYPES_INT32,
#ifdef UA_ENABLE_TYPENAMES
.typeName = "FilterOperator",
#endif
.memSize = sizeof(UA_FilterOperator),
.builtin = true,
.fixedSize = true,
.overlayable = UA_BINARY_OVERLAYABLE_INTEGER,
.membersSize = 1,
.members = FilterOperator_members },
/* QueryNextRequest */
{ .typeId = {.namespaceIndex = 0, .identifierType = UA_NODEIDTYPE_NUMERIC, .identifier.numeric = 619},
.typeIndex = UA_TYPES_QUERYNEXTREQUEST,
#ifdef UA_ENABLE_TYPENAMES
.typeName = "QueryNextRequest",
#endif
.memSize = sizeof(UA_QueryNextRequest),
.builtin = false,
.fixedSize = false,
.overlayable = false,
.membersSize = 3,
.members = QueryNextRequest_members },
/* BrowseNextRequest */
{ .typeId = {.namespaceIndex = 0, .identifierType = UA_NODEIDTYPE_NUMERIC, .identifier.numeric = 531},
.typeIndex = UA_TYPES_BROWSENEXTREQUEST,
#ifdef UA_ENABLE_TYPENAMES
.typeName = "BrowseNextRequest",
#endif
.memSize = sizeof(UA_BrowseNextRequest),
.builtin = false,
.fixedSize = false,
.overlayable = false,
.membersSize = 3,
.members = BrowseNextRequest_members },
/* CreateSubscriptionRequest */
{ .typeId = {.namespaceIndex = 0, .identifierType = UA_NODEIDTYPE_NUMERIC, .identifier.numeric = 785},
.typeIndex = UA_TYPES_CREATESUBSCRIPTIONREQUEST,
#ifdef UA_ENABLE_TYPENAMES
.typeName = "CreateSubscriptionRequest",
#endif
.memSize = sizeof(UA_CreateSubscriptionRequest),
.builtin = false,
.fixedSize = false,
.overlayable = false,
.membersSize = 7,
.members = CreateSubscriptionRequest_members },
/* VariableTypeAttributes */
{ .typeId = {.namespaceIndex = 0, .identifierType = UA_NODEIDTYPE_NUMERIC, .identifier.numeric = 364},
.typeIndex = UA_TYPES_VARIABLETYPEATTRIBUTES,
#ifdef UA_ENABLE_TYPENAMES
.typeName = "VariableTypeAttributes",
#endif
.memSize = sizeof(UA_VariableTypeAttributes),
.builtin = false,
.fixedSize = false,
.overlayable = false,
.membersSize = 10,
.members = VariableTypeAttributes_members },
/* BrowsePathResult */
{ .typeId = {.namespaceIndex = 0, .identifierType = UA_NODEIDTYPE_NUMERIC, .identifier.numeric = 549},
.typeIndex = UA_TYPES_BROWSEPATHRESULT,
#ifdef UA_ENABLE_TYPENAMES
.typeName = "BrowsePathResult",
#endif
.memSize = sizeof(UA_BrowsePathResult),
.builtin = false,
.fixedSize = false,
.overlayable = false,
.membersSize = 2,
.members = BrowsePathResult_members },
/* ModifySubscriptionResponse */
{ .typeId = {.namespaceIndex = 0, .identifierType = UA_NODEIDTYPE_NUMERIC, .identifier.numeric = 794},
.typeIndex = UA_TYPES_MODIFYSUBSCRIPTIONRESPONSE,
#ifdef UA_ENABLE_TYPENAMES
.typeName = "ModifySubscriptionResponse",
#endif
.memSize = sizeof(UA_ModifySubscriptionResponse),
.builtin = false,
.fixedSize = false,
.overlayable = false,
.membersSize = 4,
.members = ModifySubscriptionResponse_members },
/* RegisterNodesResponse */
{ .typeId = {.namespaceIndex = 0, .identifierType = UA_NODEIDTYPE_NUMERIC, .identifier.numeric = 561},
.typeIndex = UA_TYPES_REGISTERNODESRESPONSE,
#ifdef UA_ENABLE_TYPENAMES
.typeName = "RegisterNodesResponse",
#endif
.memSize = sizeof(UA_RegisterNodesResponse),
.builtin = false,
.fixedSize = false,
.overlayable = false,
.membersSize = 2,
.members = RegisterNodesResponse_members },
/* CloseSessionRequest */
{ .typeId = {.namespaceIndex = 0, .identifierType = UA_NODEIDTYPE_NUMERIC, .identifier.numeric = 471},
.typeIndex = UA_TYPES_CLOSESESSIONREQUEST,
#ifdef UA_ENABLE_TYPENAMES
.typeName = "CloseSessionRequest",
#endif
.memSize = sizeof(UA_CloseSessionRequest),
.builtin = false,
.fixedSize = false,
.overlayable = false,
.membersSize = 2,
.members = CloseSessionRequest_members },
/* ModifySubscriptionRequest */
{ .typeId = {.namespaceIndex = 0, .identifierType = UA_NODEIDTYPE_NUMERIC, .identifier.numeric = 791},
.typeIndex = UA_TYPES_MODIFYSUBSCRIPTIONREQUEST,
#ifdef UA_ENABLE_TYPENAMES
.typeName = "ModifySubscriptionRequest",
#endif
.memSize = sizeof(UA_ModifySubscriptionRequest),
.builtin = false,
.fixedSize = false,
.overlayable = false,
.membersSize = 7,
.members = ModifySubscriptionRequest_members },
/* UserTokenPolicy */
{ .typeId = {.namespaceIndex = 0, .identifierType = UA_NODEIDTYPE_NUMERIC, .identifier.numeric = 304},
.typeIndex = UA_TYPES_USERTOKENPOLICY,
#ifdef UA_ENABLE_TYPENAMES
.typeName = "UserTokenPolicy",
#endif
.memSize = sizeof(UA_UserTokenPolicy),
.builtin = false,
.fixedSize = false,
.overlayable = false,
.membersSize = 5,
.members = UserTokenPolicy_members },
/* DeleteMonitoredItemsRequest */
{ .typeId = {.namespaceIndex = 0, .identifierType = UA_NODEIDTYPE_NUMERIC, .identifier.numeric = 779},
.typeIndex = UA_TYPES_DELETEMONITOREDITEMSREQUEST,
#ifdef UA_ENABLE_TYPENAMES
.typeName = "DeleteMonitoredItemsRequest",
#endif
.memSize = sizeof(UA_DeleteMonitoredItemsRequest),
.builtin = false,
.fixedSize = false,
.overlayable = false,
.membersSize = 3,
.members = DeleteMonitoredItemsRequest_members },
/* ReferenceTypeAttributes */
{ .typeId = {.namespaceIndex = 0, .identifierType = UA_NODEIDTYPE_NUMERIC, .identifier.numeric = 367},
.typeIndex = UA_TYPES_REFERENCETYPEATTRIBUTES,
#ifdef UA_ENABLE_TYPENAMES
.typeName = "ReferenceTypeAttributes",
#endif
.memSize = sizeof(UA_ReferenceTypeAttributes),
.builtin = false,
.fixedSize = false,
.overlayable = false,
.membersSize = 8,
.members = ReferenceTypeAttributes_members },
/* BrowsePath */
{ .typeId = {.namespaceIndex = 0, .identifierType = UA_NODEIDTYPE_NUMERIC, .identifier.numeric = 543},
.typeIndex = UA_TYPES_BROWSEPATH,
#ifdef UA_ENABLE_TYPENAMES
.typeName = "BrowsePath",
#endif
.memSize = sizeof(UA_BrowsePath),
.builtin = false,
.fixedSize = false,
.overlayable = false,
.membersSize = 2,
.members = BrowsePath_members },
/* UnregisterNodesResponse */
{ .typeId = {.namespaceIndex = 0, .identifierType = UA_NODEIDTYPE_NUMERIC, .identifier.numeric = 567},
.typeIndex = UA_TYPES_UNREGISTERNODESRESPONSE,
#ifdef UA_ENABLE_TYPENAMES
.typeName = "UnregisterNodesResponse",
#endif
.memSize = sizeof(UA_UnregisterNodesResponse),
.builtin = false,
.fixedSize = false,
.overlayable = false,
.membersSize = 1,
.members = UnregisterNodesResponse_members },
/* WriteRequest */
{ .typeId = {.namespaceIndex = 0, .identifierType = UA_NODEIDTYPE_NUMERIC, .identifier.numeric = 671},
.typeIndex = UA_TYPES_WRITEREQUEST,
#ifdef UA_ENABLE_TYPENAMES
.typeName = "WriteRequest",
#endif
.memSize = sizeof(UA_WriteRequest),
.builtin = false,
.fixedSize = false,
.overlayable = false,
.membersSize = 2,
.members = WriteRequest_members },
/* ObjectAttributes */
{ .typeId = {.namespaceIndex = 0, .identifierType = UA_NODEIDTYPE_NUMERIC, .identifier.numeric = 352},
.typeIndex = UA_TYPES_OBJECTATTRIBUTES,
#ifdef UA_ENABLE_TYPENAMES
.typeName = "ObjectAttributes",
#endif
.memSize = sizeof(UA_ObjectAttributes),
.builtin = false,
.fixedSize = false,
.overlayable = false,
.membersSize = 6,
.members = ObjectAttributes_members },
/* BrowseDescription */
{ .typeId = {.namespaceIndex = 0, .identifierType = UA_NODEIDTYPE_NUMERIC, .identifier.numeric = 514},
.typeIndex = UA_TYPES_BROWSEDESCRIPTION,
#ifdef UA_ENABLE_TYPENAMES
.typeName = "BrowseDescription",
#endif
.memSize = sizeof(UA_BrowseDescription),
.builtin = false,
.fixedSize = false,
.overlayable = false,
.membersSize = 6,
.members = BrowseDescription_members },
/* RepublishRequest */
{ .typeId = {.namespaceIndex = 0, .identifierType = UA_NODEIDTYPE_NUMERIC, .identifier.numeric = 830},
.typeIndex = UA_TYPES_REPUBLISHREQUEST,
#ifdef UA_ENABLE_TYPENAMES
.typeName = "RepublishRequest",
#endif
.memSize = sizeof(UA_RepublishRequest),
.builtin = false,
.fixedSize = false,
.overlayable = false,
.membersSize = 3,
.members = RepublishRequest_members },
/* GetEndpointsRequest */
{ .typeId = {.namespaceIndex = 0, .identifierType = UA_NODEIDTYPE_NUMERIC, .identifier.numeric = 426},
.typeIndex = UA_TYPES_GETENDPOINTSREQUEST,
#ifdef UA_ENABLE_TYPENAMES
.typeName = "GetEndpointsRequest",
#endif
.memSize = sizeof(UA_GetEndpointsRequest),
.builtin = false,
.fixedSize = false,
.overlayable = false,
.membersSize = 4,
.members = GetEndpointsRequest_members },
/* PublishRequest */
{ .typeId = {.namespaceIndex = 0, .identifierType = UA_NODEIDTYPE_NUMERIC, .identifier.numeric = 824},
.typeIndex = UA_TYPES_PUBLISHREQUEST,
#ifdef UA_ENABLE_TYPENAMES
.typeName = "PublishRequest",
#endif
.memSize = sizeof(UA_PublishRequest),
.builtin = false,
.fixedSize = false,
.overlayable = false,
.membersSize = 2,
.members = PublishRequest_members },
/* AddNodesResponse */
{ .typeId = {.namespaceIndex = 0, .identifierType = UA_NODEIDTYPE_NUMERIC, .identifier.numeric = 489},
.typeIndex = UA_TYPES_ADDNODESRESPONSE,
#ifdef UA_ENABLE_TYPENAMES
.typeName = "AddNodesResponse",
#endif
.memSize = sizeof(UA_AddNodesResponse),
.builtin = false,
.fixedSize = false,
.overlayable = false,
.membersSize = 3,
.members = AddNodesResponse_members },
/* CloseSecureChannelResponse */
{ .typeId = {.namespaceIndex = 0, .identifierType = UA_NODEIDTYPE_NUMERIC, .identifier.numeric = 453},
.typeIndex = UA_TYPES_CLOSESECURECHANNELRESPONSE,
#ifdef UA_ENABLE_TYPENAMES
.typeName = "CloseSecureChannelResponse",
#endif
.memSize = sizeof(UA_CloseSecureChannelResponse),
.builtin = false,
.fixedSize = false,
.overlayable = false,
.membersSize = 1,
.members = CloseSecureChannelResponse_members },
/* ModifyMonitoredItemsRequest */
{ .typeId = {.namespaceIndex = 0, .identifierType = UA_NODEIDTYPE_NUMERIC, .identifier.numeric = 761},
.typeIndex = UA_TYPES_MODIFYMONITOREDITEMSREQUEST,
#ifdef UA_ENABLE_TYPENAMES
.typeName = "ModifyMonitoredItemsRequest",
#endif
.memSize = sizeof(UA_ModifyMonitoredItemsRequest),
.builtin = false,
.fixedSize = false,
.overlayable = false,
.membersSize = 4,
.members = ModifyMonitoredItemsRequest_members },
/* FindServersRequest */
{ .typeId = {.namespaceIndex = 0, .identifierType = UA_NODEIDTYPE_NUMERIC, .identifier.numeric = 420},
.typeIndex = UA_TYPES_FINDSERVERSREQUEST,
#ifdef UA_ENABLE_TYPENAMES
.typeName = "FindServersRequest",
#endif
.memSize = sizeof(UA_FindServersRequest),
.builtin = false,
.fixedSize = false,
.overlayable = false,
.membersSize = 4,
.members = FindServersRequest_members },
/* ReferenceDescription */
{ .typeId = {.namespaceIndex = 0, .identifierType = UA_NODEIDTYPE_NUMERIC, .identifier.numeric = 518},
.typeIndex = UA_TYPES_REFERENCEDESCRIPTION,
#ifdef UA_ENABLE_TYPENAMES
.typeName = "ReferenceDescription",
#endif
.memSize = sizeof(UA_ReferenceDescription),
.builtin = false,
.fixedSize = false,
.overlayable = false,
.membersSize = 7,
.members = ReferenceDescription_members },
/* SetPublishingModeResponse */
{ .typeId = {.namespaceIndex = 0, .identifierType = UA_NODEIDTYPE_NUMERIC, .identifier.numeric = 800},
.typeIndex = UA_TYPES_SETPUBLISHINGMODERESPONSE,
#ifdef UA_ENABLE_TYPENAMES
.typeName = "SetPublishingModeResponse",
#endif
.memSize = sizeof(UA_SetPublishingModeResponse),
.builtin = false,
.fixedSize = false,
.overlayable = false,
.membersSize = 3,
.members = SetPublishingModeResponse_members },
/* ContentFilterResult */
{ .typeId = {.namespaceIndex = 0, .identifierType = UA_NODEIDTYPE_NUMERIC, .identifier.numeric = 607},
.typeIndex = UA_TYPES_CONTENTFILTERRESULT,
#ifdef UA_ENABLE_TYPENAMES
.typeName = "ContentFilterResult",
#endif
.memSize = sizeof(UA_ContentFilterResult),
.builtin = false,
.fixedSize = false,
.overlayable = false,
.membersSize = 2,
.members = ContentFilterResult_members },
/* AddReferencesItem */
{ .typeId = {.namespaceIndex = 0, .identifierType = UA_NODEIDTYPE_NUMERIC, .identifier.numeric = 379},
.typeIndex = UA_TYPES_ADDREFERENCESITEM,
#ifdef UA_ENABLE_TYPENAMES
.typeName = "AddReferencesItem",
#endif
.memSize = sizeof(UA_AddReferencesItem),
.builtin = false,
.fixedSize = false,
.overlayable = false,
.membersSize = 6,
.members = AddReferencesItem_members },
/* QueryDataDescription */
{ .typeId = {.namespaceIndex = 0, .identifierType = UA_NODEIDTYPE_NUMERIC, .identifier.numeric = 570},
.typeIndex = UA_TYPES_QUERYDATADESCRIPTION,
#ifdef UA_ENABLE_TYPENAMES
.typeName = "QueryDataDescription",
#endif
.memSize = sizeof(UA_QueryDataDescription),
.builtin = false,
.fixedSize = false,
.overlayable = false,
.membersSize = 3,
.members = QueryDataDescription_members },
/* CreateSubscriptionResponse */
{ .typeId = {.namespaceIndex = 0, .identifierType = UA_NODEIDTYPE_NUMERIC, .identifier.numeric = 788},
.typeIndex = UA_TYPES_CREATESUBSCRIPTIONRESPONSE,
#ifdef UA_ENABLE_TYPENAMES
.typeName = "CreateSubscriptionResponse",
#endif
.memSize = sizeof(UA_CreateSubscriptionResponse),
.builtin = false,
.fixedSize = false,
.overlayable = false,
.membersSize = 5,
.members = CreateSubscriptionResponse_members },
/* DeleteSubscriptionsResponse */
{ .typeId = {.namespaceIndex = 0, .identifierType = UA_NODEIDTYPE_NUMERIC, .identifier.numeric = 848},
.typeIndex = UA_TYPES_DELETESUBSCRIPTIONSRESPONSE,
#ifdef UA_ENABLE_TYPENAMES
.typeName = "DeleteSubscriptionsResponse",
#endif
.memSize = sizeof(UA_DeleteSubscriptionsResponse),
.builtin = false,
.fixedSize = false,
.overlayable = false,
.membersSize = 3,
.members = DeleteSubscriptionsResponse_members },
/* WriteResponse */
{ .typeId = {.namespaceIndex = 0, .identifierType = UA_NODEIDTYPE_NUMERIC, .identifier.numeric = 674},
.typeIndex = UA_TYPES_WRITERESPONSE,
#ifdef UA_ENABLE_TYPENAMES
.typeName = "WriteResponse",
#endif
.memSize = sizeof(UA_WriteResponse),
.builtin = false,
.fixedSize = false,
.overlayable = false,
.membersSize = 3,
.members = WriteResponse_members },
/* DeleteReferencesResponse */
{ .typeId = {.namespaceIndex = 0, .identifierType = UA_NODEIDTYPE_NUMERIC, .identifier.numeric = 507},
.typeIndex = UA_TYPES_DELETEREFERENCESRESPONSE,
#ifdef UA_ENABLE_TYPENAMES
.typeName = "DeleteReferencesResponse",
#endif
.memSize = sizeof(UA_DeleteReferencesResponse),
.builtin = false,
.fixedSize = false,
.overlayable = false,
.membersSize = 3,
.members = DeleteReferencesResponse_members },
/* CreateMonitoredItemsResponse */
{ .typeId = {.namespaceIndex = 0, .identifierType = UA_NODEIDTYPE_NUMERIC, .identifier.numeric = 752},
.typeIndex = UA_TYPES_CREATEMONITOREDITEMSRESPONSE,
#ifdef UA_ENABLE_TYPENAMES
.typeName = "CreateMonitoredItemsResponse",
#endif
.memSize = sizeof(UA_CreateMonitoredItemsResponse),
.builtin = false,
.fixedSize = false,
.overlayable = false,
.membersSize = 3,
.members = CreateMonitoredItemsResponse_members },
/* CallResponse */
{ .typeId = {.namespaceIndex = 0, .identifierType = UA_NODEIDTYPE_NUMERIC, .identifier.numeric = 713},
.typeIndex = UA_TYPES_CALLRESPONSE,
#ifdef UA_ENABLE_TYPENAMES
.typeName = "CallResponse",
#endif
.memSize = sizeof(UA_CallResponse),
.builtin = false,
.fixedSize = false,
.overlayable = false,
.membersSize = 3,
.members = CallResponse_members },
/* DeleteNodesResponse */
{ .typeId = {.namespaceIndex = 0, .identifierType = UA_NODEIDTYPE_NUMERIC, .identifier.numeric = 501},
.typeIndex = UA_TYPES_DELETENODESRESPONSE,
#ifdef UA_ENABLE_TYPENAMES
.typeName = "DeleteNodesResponse",
#endif
.memSize = sizeof(UA_DeleteNodesResponse),
.builtin = false,
.fixedSize = false,
.overlayable = false,
.membersSize = 3,
.members = DeleteNodesResponse_members },
/* RepublishResponse */
{ .typeId = {.namespaceIndex = 0, .identifierType = UA_NODEIDTYPE_NUMERIC, .identifier.numeric = 833},
.typeIndex = UA_TYPES_REPUBLISHRESPONSE,
#ifdef UA_ENABLE_TYPENAMES
.typeName = "RepublishResponse",
#endif
.memSize = sizeof(UA_RepublishResponse),
.builtin = false,
.fixedSize = false,
.overlayable = false,
.membersSize = 2,
.members = RepublishResponse_members },
/* MonitoredItemCreateRequest */
{ .typeId = {.namespaceIndex = 0, .identifierType = UA_NODEIDTYPE_NUMERIC, .identifier.numeric = 743},
.typeIndex = UA_TYPES_MONITOREDITEMCREATEREQUEST,
#ifdef UA_ENABLE_TYPENAMES
.typeName = "MonitoredItemCreateRequest",
#endif
.memSize = sizeof(UA_MonitoredItemCreateRequest),
.builtin = false,
.fixedSize = false,
.overlayable = false,
.membersSize = 3,
.members = MonitoredItemCreateRequest_members },
/* DeleteReferencesRequest */
{ .typeId = {.namespaceIndex = 0, .identifierType = UA_NODEIDTYPE_NUMERIC, .identifier.numeric = 504},
.typeIndex = UA_TYPES_DELETEREFERENCESREQUEST,
#ifdef UA_ENABLE_TYPENAMES
.typeName = "DeleteReferencesRequest",
#endif
.memSize = sizeof(UA_DeleteReferencesRequest),
.builtin = false,
.fixedSize = false,
.overlayable = false,
.membersSize = 2,
.members = DeleteReferencesRequest_members },
/* ModifyMonitoredItemsResponse */
{ .typeId = {.namespaceIndex = 0, .identifierType = UA_NODEIDTYPE_NUMERIC, .identifier.numeric = 764},
.typeIndex = UA_TYPES_MODIFYMONITOREDITEMSRESPONSE,
#ifdef UA_ENABLE_TYPENAMES
.typeName = "ModifyMonitoredItemsResponse",
#endif
.memSize = sizeof(UA_ModifyMonitoredItemsResponse),
.builtin = false,
.fixedSize = false,
.overlayable = false,
.membersSize = 3,
.members = ModifyMonitoredItemsResponse_members },
/* ReadResponse */
{ .typeId = {.namespaceIndex = 0, .identifierType = UA_NODEIDTYPE_NUMERIC, .identifier.numeric = 632},
.typeIndex = UA_TYPES_READRESPONSE,
#ifdef UA_ENABLE_TYPENAMES
.typeName = "ReadResponse",
#endif
.memSize = sizeof(UA_ReadResponse),
.builtin = false,
.fixedSize = false,
.overlayable = false,
.membersSize = 3,
.members = ReadResponse_members },
/* AddReferencesRequest */
{ .typeId = {.namespaceIndex = 0, .identifierType = UA_NODEIDTYPE_NUMERIC, .identifier.numeric = 492},
.typeIndex = UA_TYPES_ADDREFERENCESREQUEST,
#ifdef UA_ENABLE_TYPENAMES
.typeName = "AddReferencesRequest",
#endif
.memSize = sizeof(UA_AddReferencesRequest),
.builtin = false,
.fixedSize = false,
.overlayable = false,
.membersSize = 2,
.members = AddReferencesRequest_members },
/* ReadRequest */
{ .typeId = {.namespaceIndex = 0, .identifierType = UA_NODEIDTYPE_NUMERIC, .identifier.numeric = 629},
.typeIndex = UA_TYPES_READREQUEST,
#ifdef UA_ENABLE_TYPENAMES
.typeName = "ReadRequest",
#endif
.memSize = sizeof(UA_ReadRequest),
.builtin = false,
.fixedSize = false,
.overlayable = false,
.membersSize = 4,
.members = ReadRequest_members },
/* OpenSecureChannelRequest */
{ .typeId = {.namespaceIndex = 0, .identifierType = UA_NODEIDTYPE_NUMERIC, .identifier.numeric = 444},
.typeIndex = UA_TYPES_OPENSECURECHANNELREQUEST,
#ifdef UA_ENABLE_TYPENAMES
.typeName = "OpenSecureChannelRequest",
#endif
.memSize = sizeof(UA_OpenSecureChannelRequest),
.builtin = false,
.fixedSize = false,
.overlayable = false,
.membersSize = 6,
.members = OpenSecureChannelRequest_members },
/* AddNodesItem */
{ .typeId = {.namespaceIndex = 0, .identifierType = UA_NODEIDTYPE_NUMERIC, .identifier.numeric = 376},
.typeIndex = UA_TYPES_ADDNODESITEM,
#ifdef UA_ENABLE_TYPENAMES
.typeName = "AddNodesItem",
#endif
.memSize = sizeof(UA_AddNodesItem),
.builtin = false,
.fixedSize = false,
.overlayable = false,
.membersSize = 7,
.members = AddNodesItem_members },
/* ApplicationDescription */
{ .typeId = {.namespaceIndex = 0, .identifierType = UA_NODEIDTYPE_NUMERIC, .identifier.numeric = 308},
.typeIndex = UA_TYPES_APPLICATIONDESCRIPTION,
#ifdef UA_ENABLE_TYPENAMES
.typeName = "ApplicationDescription",
#endif
.memSize = sizeof(UA_ApplicationDescription),
.builtin = false,
.fixedSize = false,
.overlayable = false,
.membersSize = 7,
.members = ApplicationDescription_members },
/* NodeTypeDescription */
{ .typeId = {.namespaceIndex = 0, .identifierType = UA_NODEIDTYPE_NUMERIC, .identifier.numeric = 573},
.typeIndex = UA_TYPES_NODETYPEDESCRIPTION,
#ifdef UA_ENABLE_TYPENAMES
.typeName = "NodeTypeDescription",
#endif
.memSize = sizeof(UA_NodeTypeDescription),
.builtin = false,
.fixedSize = false,
.overlayable = false,
.membersSize = 3,
.members = NodeTypeDescription_members },
/* FindServersResponse */
{ .typeId = {.namespaceIndex = 0, .identifierType = UA_NODEIDTYPE_NUMERIC, .identifier.numeric = 423},
.typeIndex = UA_TYPES_FINDSERVERSRESPONSE,
#ifdef UA_ENABLE_TYPENAMES
.typeName = "FindServersResponse",
#endif
.memSize = sizeof(UA_FindServersResponse),
.builtin = false,
.fixedSize = false,
.overlayable = false,
.membersSize = 2,
.members = FindServersResponse_members },
/* ServerStatusDataType */
{ .typeId = {.namespaceIndex = 0, .identifierType = UA_NODEIDTYPE_NUMERIC, .identifier.numeric = 862},
.typeIndex = UA_TYPES_SERVERSTATUSDATATYPE,
#ifdef UA_ENABLE_TYPENAMES
.typeName = "ServerStatusDataType",
#endif
.memSize = sizeof(UA_ServerStatusDataType),
.builtin = false,
.fixedSize = false,
.overlayable = false,
.membersSize = 6,
.members = ServerStatusDataType_members },
/* AddReferencesResponse */
{ .typeId = {.namespaceIndex = 0, .identifierType = UA_NODEIDTYPE_NUMERIC, .identifier.numeric = 495},
.typeIndex = UA_TYPES_ADDREFERENCESRESPONSE,
#ifdef UA_ENABLE_TYPENAMES
.typeName = "AddReferencesResponse",
#endif
.memSize = sizeof(UA_AddReferencesResponse),
.builtin = false,
.fixedSize = false,
.overlayable = false,
.membersSize = 3,
.members = AddReferencesResponse_members },
/* TranslateBrowsePathsToNodeIdsResponse */
{ .typeId = {.namespaceIndex = 0, .identifierType = UA_NODEIDTYPE_NUMERIC, .identifier.numeric = 555},
.typeIndex = UA_TYPES_TRANSLATEBROWSEPATHSTONODEIDSRESPONSE,
#ifdef UA_ENABLE_TYPENAMES
.typeName = "TranslateBrowsePathsToNodeIdsResponse",
#endif
.memSize = sizeof(UA_TranslateBrowsePathsToNodeIdsResponse),
.builtin = false,
.fixedSize = false,
.overlayable = false,
.membersSize = 3,
.members = TranslateBrowsePathsToNodeIdsResponse_members },
/* ContentFilterElement */
{ .typeId = {.namespaceIndex = 0, .identifierType = UA_NODEIDTYPE_NUMERIC, .identifier.numeric = 583},
.typeIndex = UA_TYPES_CONTENTFILTERELEMENT,
#ifdef UA_ENABLE_TYPENAMES
.typeName = "ContentFilterElement",
#endif
.memSize = sizeof(UA_ContentFilterElement),
.builtin = false,
.fixedSize = false,
.overlayable = false,
.membersSize = 2,
.members = ContentFilterElement_members },
/* TranslateBrowsePathsToNodeIdsRequest */
{ .typeId = {.namespaceIndex = 0, .identifierType = UA_NODEIDTYPE_NUMERIC, .identifier.numeric = 552},
.typeIndex = UA_TYPES_TRANSLATEBROWSEPATHSTONODEIDSREQUEST,
#ifdef UA_ENABLE_TYPENAMES
.typeName = "TranslateBrowsePathsToNodeIdsRequest",
#endif
.memSize = sizeof(UA_TranslateBrowsePathsToNodeIdsRequest),
.builtin = false,
.fixedSize = false,
.overlayable = false,
.membersSize = 2,
.members = TranslateBrowsePathsToNodeIdsRequest_members },
/* CloseSessionResponse */
{ .typeId = {.namespaceIndex = 0, .identifierType = UA_NODEIDTYPE_NUMERIC, .identifier.numeric = 474},
.typeIndex = UA_TYPES_CLOSESESSIONRESPONSE,
#ifdef UA_ENABLE_TYPENAMES
.typeName = "CloseSessionResponse",
#endif
.memSize = sizeof(UA_CloseSessionResponse),
.builtin = false,
.fixedSize = false,
.overlayable = false,
.membersSize = 1,
.members = CloseSessionResponse_members },
/* ServiceFault */
{ .typeId = {.namespaceIndex = 0, .identifierType = UA_NODEIDTYPE_NUMERIC, .identifier.numeric = 395},
.typeIndex = UA_TYPES_SERVICEFAULT,
#ifdef UA_ENABLE_TYPENAMES
.typeName = "ServiceFault",
#endif
.memSize = sizeof(UA_ServiceFault),
.builtin = false,
.fixedSize = false,
.overlayable = false,
.membersSize = 1,
.members = ServiceFault_members },
/* CreateMonitoredItemsRequest */
{ .typeId = {.namespaceIndex = 0, .identifierType = UA_NODEIDTYPE_NUMERIC, .identifier.numeric = 749},
.typeIndex = UA_TYPES_CREATEMONITOREDITEMSREQUEST,
#ifdef UA_ENABLE_TYPENAMES
.typeName = "CreateMonitoredItemsRequest",
#endif
.memSize = sizeof(UA_CreateMonitoredItemsRequest),
.builtin = false,
.fixedSize = false,
.overlayable = false,
.membersSize = 4,
.members = CreateMonitoredItemsRequest_members },
/* ContentFilter */
{ .typeId = {.namespaceIndex = 0, .identifierType = UA_NODEIDTYPE_NUMERIC, .identifier.numeric = 586},
.typeIndex = UA_TYPES_CONTENTFILTER,
#ifdef UA_ENABLE_TYPENAMES
.typeName = "ContentFilter",
#endif
.memSize = sizeof(UA_ContentFilter),
.builtin = false,
.fixedSize = false,
.overlayable = false,
.membersSize = 1,
.members = ContentFilter_members },
/* QueryFirstResponse */
{ .typeId = {.namespaceIndex = 0, .identifierType = UA_NODEIDTYPE_NUMERIC, .identifier.numeric = 616},
.typeIndex = UA_TYPES_QUERYFIRSTRESPONSE,
#ifdef UA_ENABLE_TYPENAMES
.typeName = "QueryFirstResponse",
#endif
.memSize = sizeof(UA_QueryFirstResponse),
.builtin = false,
.fixedSize = false,
.overlayable = false,
.membersSize = 6,
.members = QueryFirstResponse_members },
/* AddNodesRequest */
{ .typeId = {.namespaceIndex = 0, .identifierType = UA_NODEIDTYPE_NUMERIC, .identifier.numeric = 486},
.typeIndex = UA_TYPES_ADDNODESREQUEST,
#ifdef UA_ENABLE_TYPENAMES
.typeName = "AddNodesRequest",
#endif
.memSize = sizeof(UA_AddNodesRequest),
.builtin = false,
.fixedSize = false,
.overlayable = false,
.membersSize = 2,
.members = AddNodesRequest_members },
/* BrowseRequest */
{ .typeId = {.namespaceIndex = 0, .identifierType = UA_NODEIDTYPE_NUMERIC, .identifier.numeric = 525},
.typeIndex = UA_TYPES_BROWSEREQUEST,
#ifdef UA_ENABLE_TYPENAMES
.typeName = "BrowseRequest",
#endif
.memSize = sizeof(UA_BrowseRequest),
.builtin = false,
.fixedSize = false,
.overlayable = false,
.membersSize = 4,
.members = BrowseRequest_members },
/* BrowseResult */
{ .typeId = {.namespaceIndex = 0, .identifierType = UA_NODEIDTYPE_NUMERIC, .identifier.numeric = 522},
.typeIndex = UA_TYPES_BROWSERESULT,
#ifdef UA_ENABLE_TYPENAMES
.typeName = "BrowseResult",
#endif
.memSize = sizeof(UA_BrowseResult),
.builtin = false,
.fixedSize = false,
.overlayable = false,
.membersSize = 3,
.members = BrowseResult_members },
/* CreateSessionRequest */
{ .typeId = {.namespaceIndex = 0, .identifierType = UA_NODEIDTYPE_NUMERIC, .identifier.numeric = 459},
.typeIndex = UA_TYPES_CREATESESSIONREQUEST,
#ifdef UA_ENABLE_TYPENAMES
.typeName = "CreateSessionRequest",
#endif
.memSize = sizeof(UA_CreateSessionRequest),
.builtin = false,
.fixedSize = false,
.overlayable = false,
.membersSize = 9,
.members = CreateSessionRequest_members },
/* EndpointDescription */
{ .typeId = {.namespaceIndex = 0, .identifierType = UA_NODEIDTYPE_NUMERIC, .identifier.numeric = 312},
.typeIndex = UA_TYPES_ENDPOINTDESCRIPTION,
#ifdef UA_ENABLE_TYPENAMES
.typeName = "EndpointDescription",
#endif
.memSize = sizeof(UA_EndpointDescription),
.builtin = false,
.fixedSize = false,
.overlayable = false,
.membersSize = 8,
.members = EndpointDescription_members },
/* GetEndpointsResponse */
{ .typeId = {.namespaceIndex = 0, .identifierType = UA_NODEIDTYPE_NUMERIC, .identifier.numeric = 429},
.typeIndex = UA_TYPES_GETENDPOINTSRESPONSE,
#ifdef UA_ENABLE_TYPENAMES
.typeName = "GetEndpointsResponse",
#endif
.memSize = sizeof(UA_GetEndpointsResponse),
.builtin = false,
.fixedSize = false,
.overlayable = false,
.membersSize = 2,
.members = GetEndpointsResponse_members },
/* BrowseNextResponse */
{ .typeId = {.namespaceIndex = 0, .identifierType = UA_NODEIDTYPE_NUMERIC, .identifier.numeric = 534},
.typeIndex = UA_TYPES_BROWSENEXTRESPONSE,
#ifdef UA_ENABLE_TYPENAMES
.typeName = "BrowseNextResponse",
#endif
.memSize = sizeof(UA_BrowseNextResponse),
.builtin = false,
.fixedSize = false,
.overlayable = false,
.membersSize = 3,
.members = BrowseNextResponse_members },
/* BrowseResponse */
{ .typeId = {.namespaceIndex = 0, .identifierType = UA_NODEIDTYPE_NUMERIC, .identifier.numeric = 528},
.typeIndex = UA_TYPES_BROWSERESPONSE,
#ifdef UA_ENABLE_TYPENAMES
.typeName = "BrowseResponse",
#endif
.memSize = sizeof(UA_BrowseResponse),
.builtin = false,
.fixedSize = false,
.overlayable = false,
.membersSize = 3,
.members = BrowseResponse_members },
/* CreateSessionResponse */
{ .typeId = {.namespaceIndex = 0, .identifierType = UA_NODEIDTYPE_NUMERIC, .identifier.numeric = 462},
.typeIndex = UA_TYPES_CREATESESSIONRESPONSE,
#ifdef UA_ENABLE_TYPENAMES
.typeName = "CreateSessionResponse",
#endif
.memSize = sizeof(UA_CreateSessionResponse),
.builtin = false,
.fixedSize = false,
.overlayable = false,
.membersSize = 10,
.members = CreateSessionResponse_members },
/* QueryFirstRequest */
{ .typeId = {.namespaceIndex = 0, .identifierType = UA_NODEIDTYPE_NUMERIC, .identifier.numeric = 613},
.typeIndex = UA_TYPES_QUERYFIRSTREQUEST,
#ifdef UA_ENABLE_TYPENAMES
.typeName = "QueryFirstRequest",
#endif
.memSize = sizeof(UA_QueryFirstRequest),
.builtin = false,
.fixedSize = false,
.overlayable = false,
.membersSize = 6,
.members = QueryFirstRequest_members },
};
/*********************************** amalgamated original file "/home/wn/Sources/open62541-open62541-395ce48/build/src_generated/ua_transport_generated.c" ***********************************/
/* Generated from Opc.Ua.Types.bsd, Custom.Opc.Ua.Transport.bsd with script /home/wn/Sources/open62541-open62541-395ce48/tools/generate_datatypes.py
* on host debianX by user wn at 2016-06-07 04:48:38 */
/* SecureConversationMessageAbortBody */
static UA_DataTypeMember SecureConversationMessageAbortBody_members[2] = {
{ .memberTypeIndex = UA_TYPES_UINT32,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "error",
#endif
.namespaceZero = true,
.padding = 0,
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_STRING,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "reason",
#endif
.namespaceZero = true,
.padding = offsetof(UA_SecureConversationMessageAbortBody, reason) - offsetof(UA_SecureConversationMessageAbortBody, error) - sizeof(UA_UInt32),
.isArray = false
},};
/* SecureConversationMessageFooter */
static UA_DataTypeMember SecureConversationMessageFooter_members[2] = {
{ .memberTypeIndex = UA_TYPES_BYTE,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "padding",
#endif
.namespaceZero = true,
.padding = 0,
.isArray = true
},
{ .memberTypeIndex = UA_TYPES_BYTE,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "signature",
#endif
.namespaceZero = true,
.padding = offsetof(UA_SecureConversationMessageFooter, signature) - offsetof(UA_SecureConversationMessageFooter, padding) - sizeof(void*),
.isArray = false
},};
/* TcpHelloMessage */
static UA_DataTypeMember TcpHelloMessage_members[6] = {
{ .memberTypeIndex = UA_TYPES_UINT32,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "protocolVersion",
#endif
.namespaceZero = true,
.padding = 0,
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_UINT32,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "receiveBufferSize",
#endif
.namespaceZero = true,
.padding = offsetof(UA_TcpHelloMessage, receiveBufferSize) - offsetof(UA_TcpHelloMessage, protocolVersion) - sizeof(UA_UInt32),
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_UINT32,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "sendBufferSize",
#endif
.namespaceZero = true,
.padding = offsetof(UA_TcpHelloMessage, sendBufferSize) - offsetof(UA_TcpHelloMessage, receiveBufferSize) - sizeof(UA_UInt32),
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_UINT32,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "maxMessageSize",
#endif
.namespaceZero = true,
.padding = offsetof(UA_TcpHelloMessage, maxMessageSize) - offsetof(UA_TcpHelloMessage, sendBufferSize) - sizeof(UA_UInt32),
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_UINT32,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "maxChunkCount",
#endif
.namespaceZero = true,
.padding = offsetof(UA_TcpHelloMessage, maxChunkCount) - offsetof(UA_TcpHelloMessage, maxMessageSize) - sizeof(UA_UInt32),
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_STRING,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "endpointUrl",
#endif
.namespaceZero = true,
.padding = offsetof(UA_TcpHelloMessage, endpointUrl) - offsetof(UA_TcpHelloMessage, maxChunkCount) - sizeof(UA_UInt32),
.isArray = false
},};
/* MessageType */
static UA_DataTypeMember MessageType_members[1] = {
{ .memberTypeIndex = UA_TYPES_INT32,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "",
#endif
.namespaceZero = true,
.padding = 0,
.isArray = false
},};
/* AsymmetricAlgorithmSecurityHeader */
static UA_DataTypeMember AsymmetricAlgorithmSecurityHeader_members[3] = {
{ .memberTypeIndex = UA_TYPES_BYTESTRING,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "securityPolicyUri",
#endif
.namespaceZero = true,
.padding = 0,
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_BYTESTRING,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "senderCertificate",
#endif
.namespaceZero = true,
.padding = offsetof(UA_AsymmetricAlgorithmSecurityHeader, senderCertificate) - offsetof(UA_AsymmetricAlgorithmSecurityHeader, securityPolicyUri) - sizeof(UA_ByteString),
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_BYTESTRING,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "receiverCertificateThumbprint",
#endif
.namespaceZero = true,
.padding = offsetof(UA_AsymmetricAlgorithmSecurityHeader, receiverCertificateThumbprint) - offsetof(UA_AsymmetricAlgorithmSecurityHeader, senderCertificate) - sizeof(UA_ByteString),
.isArray = false
},};
/* TcpAcknowledgeMessage */
static UA_DataTypeMember TcpAcknowledgeMessage_members[5] = {
{ .memberTypeIndex = UA_TYPES_UINT32,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "protocolVersion",
#endif
.namespaceZero = true,
.padding = 0,
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_UINT32,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "receiveBufferSize",
#endif
.namespaceZero = true,
.padding = offsetof(UA_TcpAcknowledgeMessage, receiveBufferSize) - offsetof(UA_TcpAcknowledgeMessage, protocolVersion) - sizeof(UA_UInt32),
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_UINT32,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "sendBufferSize",
#endif
.namespaceZero = true,
.padding = offsetof(UA_TcpAcknowledgeMessage, sendBufferSize) - offsetof(UA_TcpAcknowledgeMessage, receiveBufferSize) - sizeof(UA_UInt32),
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_UINT32,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "maxMessageSize",
#endif
.namespaceZero = true,
.padding = offsetof(UA_TcpAcknowledgeMessage, maxMessageSize) - offsetof(UA_TcpAcknowledgeMessage, sendBufferSize) - sizeof(UA_UInt32),
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_UINT32,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "maxChunkCount",
#endif
.namespaceZero = true,
.padding = offsetof(UA_TcpAcknowledgeMessage, maxChunkCount) - offsetof(UA_TcpAcknowledgeMessage, maxMessageSize) - sizeof(UA_UInt32),
.isArray = false
},};
/* SequenceHeader */
static UA_DataTypeMember SequenceHeader_members[2] = {
{ .memberTypeIndex = UA_TYPES_UINT32,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "sequenceNumber",
#endif
.namespaceZero = true,
.padding = 0,
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_UINT32,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "requestId",
#endif
.namespaceZero = true,
.padding = offsetof(UA_SequenceHeader, requestId) - offsetof(UA_SequenceHeader, sequenceNumber) - sizeof(UA_UInt32),
.isArray = false
},};
/* TcpMessageHeader */
static UA_DataTypeMember TcpMessageHeader_members[2] = {
{ .memberTypeIndex = UA_TYPES_UINT32,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "messageTypeAndChunkType",
#endif
.namespaceZero = true,
.padding = 0,
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_UINT32,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "messageSize",
#endif
.namespaceZero = true,
.padding = offsetof(UA_TcpMessageHeader, messageSize) - offsetof(UA_TcpMessageHeader, messageTypeAndChunkType) - sizeof(UA_UInt32),
.isArray = false
},};
/* ChunkType */
static UA_DataTypeMember ChunkType_members[1] = {
{ .memberTypeIndex = UA_TYPES_INT32,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "",
#endif
.namespaceZero = true,
.padding = 0,
.isArray = false
},};
/* SymmetricAlgorithmSecurityHeader */
static UA_DataTypeMember SymmetricAlgorithmSecurityHeader_members[1] = {
{ .memberTypeIndex = UA_TYPES_UINT32,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "tokenId",
#endif
.namespaceZero = true,
.padding = 0,
.isArray = false
},};
/* SecureConversationMessageHeader */
static UA_DataTypeMember SecureConversationMessageHeader_members[2] = {
{ .memberTypeIndex = UA_TRANSPORT_TCPMESSAGEHEADER,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "messageHeader",
#endif
.namespaceZero = false,
.padding = 0,
.isArray = false
},
{ .memberTypeIndex = UA_TYPES_UINT32,
#ifdef UA_ENABLE_TYPENAMES
.memberName = "secureChannelId",
#endif
.namespaceZero = true,
.padding = offsetof(UA_SecureConversationMessageHeader, secureChannelId) - offsetof(UA_SecureConversationMessageHeader, messageHeader) - sizeof(UA_TcpMessageHeader),
.isArray = false
},};
const UA_DataType UA_TRANSPORT[UA_TRANSPORT_COUNT] = {
/* SecureConversationMessageAbortBody */
{ .typeId = {.namespaceIndex = 0, .identifierType = UA_NODEIDTYPE_NUMERIC, .identifier.numeric = 0},
.typeIndex = UA_TRANSPORT_SECURECONVERSATIONMESSAGEABORTBODY,
#ifdef UA_ENABLE_TYPENAMES
.typeName = "SecureConversationMessageAbortBody",
#endif
.memSize = sizeof(UA_SecureConversationMessageAbortBody),
.builtin = false,
.fixedSize = false,
.overlayable = false,
.membersSize = 2,
.members = SecureConversationMessageAbortBody_members },
/* SecureConversationMessageFooter */
{ .typeId = {.namespaceIndex = 0, .identifierType = UA_NODEIDTYPE_NUMERIC, .identifier.numeric = 0},
.typeIndex = UA_TRANSPORT_SECURECONVERSATIONMESSAGEFOOTER,
#ifdef UA_ENABLE_TYPENAMES
.typeName = "SecureConversationMessageFooter",
#endif
.memSize = sizeof(UA_SecureConversationMessageFooter),
.builtin = false,
.fixedSize = false,
.overlayable = false,
.membersSize = 2,
.members = SecureConversationMessageFooter_members },
/* TcpHelloMessage */
{ .typeId = {.namespaceIndex = 0, .identifierType = UA_NODEIDTYPE_NUMERIC, .identifier.numeric = 0},
.typeIndex = UA_TRANSPORT_TCPHELLOMESSAGE,
#ifdef UA_ENABLE_TYPENAMES
.typeName = "TcpHelloMessage",
#endif
.memSize = sizeof(UA_TcpHelloMessage),
.builtin = false,
.fixedSize = false,
.overlayable = false,
.membersSize = 6,
.members = TcpHelloMessage_members },
/* MessageType */
{ .typeId = {.namespaceIndex = 0, .identifierType = UA_NODEIDTYPE_NUMERIC, .identifier.numeric = 0},
.typeIndex = UA_TYPES_INT32,
#ifdef UA_ENABLE_TYPENAMES
.typeName = "MessageType",
#endif
.memSize = sizeof(UA_MessageType),
.builtin = true,
.fixedSize = true,
.overlayable = UA_BINARY_OVERLAYABLE_INTEGER,
.membersSize = 1,
.members = MessageType_members },
/* AsymmetricAlgorithmSecurityHeader */
{ .typeId = {.namespaceIndex = 0, .identifierType = UA_NODEIDTYPE_NUMERIC, .identifier.numeric = 0},
.typeIndex = UA_TRANSPORT_ASYMMETRICALGORITHMSECURITYHEADER,
#ifdef UA_ENABLE_TYPENAMES
.typeName = "AsymmetricAlgorithmSecurityHeader",
#endif
.memSize = sizeof(UA_AsymmetricAlgorithmSecurityHeader),
.builtin = false,
.fixedSize = false,
.overlayable = false,
.membersSize = 3,
.members = AsymmetricAlgorithmSecurityHeader_members },
/* TcpAcknowledgeMessage */
{ .typeId = {.namespaceIndex = 0, .identifierType = UA_NODEIDTYPE_NUMERIC, .identifier.numeric = 0},
.typeIndex = UA_TRANSPORT_TCPACKNOWLEDGEMESSAGE,
#ifdef UA_ENABLE_TYPENAMES
.typeName = "TcpAcknowledgeMessage",
#endif
.memSize = sizeof(UA_TcpAcknowledgeMessage),
.builtin = false,
.fixedSize = true,
.overlayable = 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)),
.membersSize = 5,
.members = TcpAcknowledgeMessage_members },
/* SequenceHeader */
{ .typeId = {.namespaceIndex = 0, .identifierType = UA_NODEIDTYPE_NUMERIC, .identifier.numeric = 0},
.typeIndex = UA_TRANSPORT_SEQUENCEHEADER,
#ifdef UA_ENABLE_TYPENAMES
.typeName = "SequenceHeader",
#endif
.memSize = sizeof(UA_SequenceHeader),
.builtin = false,
.fixedSize = true,
.overlayable = true && UA_BINARY_OVERLAYABLE_INTEGER && UA_BINARY_OVERLAYABLE_INTEGER && offsetof(UA_SequenceHeader, requestId) == (offsetof(UA_SequenceHeader, sequenceNumber) + sizeof(UA_UInt32)),
.membersSize = 2,
.members = SequenceHeader_members },
/* TcpMessageHeader */
{ .typeId = {.namespaceIndex = 0, .identifierType = UA_NODEIDTYPE_NUMERIC, .identifier.numeric = 0},
.typeIndex = UA_TRANSPORT_TCPMESSAGEHEADER,
#ifdef UA_ENABLE_TYPENAMES
.typeName = "TcpMessageHeader",
#endif
.memSize = sizeof(UA_TcpMessageHeader),
.builtin = false,
.fixedSize = true,
.overlayable = true && UA_BINARY_OVERLAYABLE_INTEGER && UA_BINARY_OVERLAYABLE_INTEGER && offsetof(UA_TcpMessageHeader, messageSize) == (offsetof(UA_TcpMessageHeader, messageTypeAndChunkType) + sizeof(UA_UInt32)),
.membersSize = 2,
.members = TcpMessageHeader_members },
/* ChunkType */
{ .typeId = {.namespaceIndex = 0, .identifierType = UA_NODEIDTYPE_NUMERIC, .identifier.numeric = 0},
.typeIndex = UA_TYPES_INT32,
#ifdef UA_ENABLE_TYPENAMES
.typeName = "ChunkType",
#endif
.memSize = sizeof(UA_ChunkType),
.builtin = true,
.fixedSize = true,
.overlayable = UA_BINARY_OVERLAYABLE_INTEGER,
.membersSize = 1,
.members = ChunkType_members },
/* SymmetricAlgorithmSecurityHeader */
{ .typeId = {.namespaceIndex = 0, .identifierType = UA_NODEIDTYPE_NUMERIC, .identifier.numeric = 0},
.typeIndex = UA_TRANSPORT_SYMMETRICALGORITHMSECURITYHEADER,
#ifdef UA_ENABLE_TYPENAMES
.typeName = "SymmetricAlgorithmSecurityHeader",
#endif
.memSize = sizeof(UA_SymmetricAlgorithmSecurityHeader),
.builtin = false,
.fixedSize = true,
.overlayable = true && UA_BINARY_OVERLAYABLE_INTEGER,
.membersSize = 1,
.members = SymmetricAlgorithmSecurityHeader_members },
/* SecureConversationMessageHeader */
{ .typeId = {.namespaceIndex = 0, .identifierType = UA_NODEIDTYPE_NUMERIC, .identifier.numeric = 0},
.typeIndex = UA_TRANSPORT_SECURECONVERSATIONMESSAGEHEADER,
#ifdef UA_ENABLE_TYPENAMES
.typeName = "SecureConversationMessageHeader",
#endif
.memSize = sizeof(UA_SecureConversationMessageHeader),
.builtin = false,
.fixedSize = true,
.overlayable = 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)),
.membersSize = 2,
.members = SecureConversationMessageHeader_members },
};
/*********************************** amalgamated original file "/home/wn/Sources/open62541-open62541-395ce48/src/ua_connection.c" ***********************************/
// max message size is 64k
const UA_ConnectionConfig UA_ConnectionConfig_standard =
{.protocolVersion = 0, .sendBufferSize = 65536, .recvBufferSize = 65536,
.maxMessageSize = 1048576, .maxChunkCount = 16};
void UA_Connection_init(UA_Connection *connection) {
connection->state = UA_CONNECTION_CLOSED;
connection->localConf = UA_ConnectionConfig_standard;
connection->remoteConf = UA_ConnectionConfig_standard;
connection->channel = NULL;
connection->sockfd = 0;
connection->handle = NULL;
UA_ByteString_init(&connection->incompleteMessage);
connection->send = NULL;
connection->close = NULL;
connection->recv = NULL;
connection->getSendBuffer = NULL;
connection->releaseSendBuffer = NULL;
connection->releaseRecvBuffer = NULL;
}
void UA_Connection_deleteMembers(UA_Connection *connection) {
UA_ByteString_deleteMembers(&connection->incompleteMessage);
}
UA_StatusCode
UA_Connection_completeMessages(UA_Connection *connection, UA_ByteString * UA_RESTRICT message,
UA_Boolean * UA_RESTRICT realloced) {
UA_ByteString *current = message;
*realloced = false;
if(connection->incompleteMessage.length > 0) {
/* concat the existing incomplete message with the new message */
UA_Byte *data = UA_realloc(connection->incompleteMessage.data,
connection->incompleteMessage.length + message->length);
if(!data) {
/* not enough memory */
UA_ByteString_deleteMembers(&connection->incompleteMessage);
connection->releaseRecvBuffer(connection, message);
return UA_STATUSCODE_BADOUTOFMEMORY;
}
memcpy(&data[connection->incompleteMessage.length], message->data, message->length);
connection->incompleteMessage.data = data;
connection->incompleteMessage.length += message->length;
connection->releaseRecvBuffer(connection, message);
current = &connection->incompleteMessage;
*realloced = true;
}
/* the while loop sets pos to the first element after the last complete message. if a message
contains garbage, the buffer length is set to contain only the "good" messages before. */
size_t pos = 0;
size_t delete_at = current->length-1; // garbled message after this point
while(current->length - pos >= 16) {
UA_UInt32 msgtype = (UA_UInt32)current->data[pos] +
((UA_UInt32)current->data[pos+1] << 8) +
((UA_UInt32)current->data[pos+2] << 16);
if(msgtype != ('M' + ('S' << 8) + ('G' << 16)) &&
msgtype != ('O' + ('P' << 8) + ('N' << 16)) &&
msgtype != ('H' + ('E' << 8) + ('L' << 16)) &&
msgtype != ('A' + ('C' << 8) + ('K' << 16)) &&
msgtype != ('C' + ('L' << 8) + ('O' << 16))) {
/* the message type is not recognized */
delete_at = pos; // throw the remaining message away
break;
}
UA_UInt32 length = 0;
size_t length_pos = pos + 4;
UA_StatusCode retval = UA_UInt32_decodeBinary(current, &length_pos, &length);
if(retval != UA_STATUSCODE_GOOD || length < 16 || length > connection->localConf.recvBufferSize) {
/* the message size is not allowed. throw the remaining bytestring away */
delete_at = pos;
break;
}
if(length + pos > current->length)
break; /* the message is incomplete. keep the beginning */
pos += length;
}
/* throw the message away */
if(delete_at == 0) {
if(!*realloced) {
connection->releaseRecvBuffer(connection, message);
*realloced = true;
} else
UA_ByteString_deleteMembers(current);
return UA_STATUSCODE_GOOD;
}
/* no complete message at all */
if(pos == 0) {
if(!*realloced) {
/* store the buffer in the connection */
UA_ByteString_copy(current, &connection->incompleteMessage);
connection->releaseRecvBuffer(connection, message);
*realloced = true;
}
return UA_STATUSCODE_GOOD;
}
/* there remains an incomplete message at the end */
if(current->length != pos) {
UA_Byte *data = UA_malloc(current->length - pos);
if(!data) {
UA_ByteString_deleteMembers(&connection->incompleteMessage);
if(!*realloced) {
connection->releaseRecvBuffer(connection, message);
*realloced = true;
}
return UA_STATUSCODE_BADOUTOFMEMORY;
}
size_t newlength = current->length - pos;
memcpy(data, &current->data[pos], newlength);
current->length = pos;
if(*realloced)
*message = *current;
connection->incompleteMessage.data = data;
connection->incompleteMessage.length = newlength;
return UA_STATUSCODE_GOOD;
}
if(current == &connection->incompleteMessage) {
*message = *current;
connection->incompleteMessage = UA_BYTESTRING_NULL;
}
return UA_STATUSCODE_GOOD;
}
#if (__GNUC__ >= 4 && __GNUC_MINOR__ >= 6)
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wextra"
#pragma GCC diagnostic ignored "-Wcast-qual"
#pragma GCC diagnostic ignored "-Wunused-value"
#endif
void UA_Connection_detachSecureChannel(UA_Connection *connection) {
#ifdef UA_ENABLE_MULTITHREADING
UA_SecureChannel *channel = connection->channel;
if(channel)
uatomic_cmpxchg(&channel->connection, connection, NULL);
uatomic_set(&connection->channel, NULL);
#else
if(connection->channel)
connection->channel->connection = NULL;
connection->channel = NULL;
#endif
}
void UA_Connection_attachSecureChannel(UA_Connection *connection, UA_SecureChannel *channel) {
#ifdef UA_ENABLE_MULTITHREADING
if(uatomic_cmpxchg(&channel->connection, NULL, connection) == NULL)
uatomic_set((void**)&connection->channel, (void*)channel);
#else
if(channel->connection != NULL)
return;
channel->connection = connection;
connection->channel = channel;
#endif
}
#if (__GNUC__ >= 4 && __GNUC_MINOR__ >= 6)
#pragma GCC diagnostic pop
#endif
/*********************************** amalgamated original file "/home/wn/Sources/open62541-open62541-395ce48/src/ua_securechannel.c" ***********************************/
#define UA_SECURE_MESSAGE_HEADER_LENGTH 24
void UA_SecureChannel_init(UA_SecureChannel *channel) {
UA_MessageSecurityMode_init(&channel->securityMode);
UA_ChannelSecurityToken_init(&channel->securityToken);
UA_ChannelSecurityToken_init(&channel->nextSecurityToken);
UA_AsymmetricAlgorithmSecurityHeader_init(&channel->clientAsymAlgSettings);
UA_AsymmetricAlgorithmSecurityHeader_init(&channel->serverAsymAlgSettings);
UA_ByteString_init(&channel->clientNonce);
UA_ByteString_init(&channel->serverNonce);
channel->sequenceNumber = 0;
channel->connection = NULL;
LIST_INIT(&channel->sessions);
LIST_INIT(&channel->chunks);
}
void UA_SecureChannel_deleteMembersCleanup(UA_SecureChannel *channel) {
UA_AsymmetricAlgorithmSecurityHeader_deleteMembers(&channel->serverAsymAlgSettings);
UA_ByteString_deleteMembers(&channel->serverNonce);
UA_AsymmetricAlgorithmSecurityHeader_deleteMembers(&channel->clientAsymAlgSettings);
UA_ByteString_deleteMembers(&channel->clientNonce);
UA_ChannelSecurityToken_deleteMembers(&channel->securityToken);
UA_ChannelSecurityToken_deleteMembers(&channel->nextSecurityToken);
UA_Connection *c = channel->connection;
if(c) {
UA_Connection_detachSecureChannel(c);
if(c->close)
c->close(c);
}
/* just remove the pointers and free the linked list (not the sessions) */
struct SessionEntry *se, *temp;
LIST_FOREACH_SAFE(se, &channel->sessions, pointers, temp) {
if(se->session)
se->session->channel = NULL;
LIST_REMOVE(se, pointers);
UA_free(se);
}
struct ChunkEntry *ch, *temp_ch;
LIST_FOREACH_SAFE(ch, &channel->chunks, pointers, temp_ch) {
UA_ByteString_deleteMembers(&ch->bytes);
LIST_REMOVE(ch, pointers);
UA_free(ch);
}
}
//TODO implement real nonce generator - DUMMY function
UA_StatusCode UA_SecureChannel_generateNonce(UA_ByteString *nonce) {
if(!(nonce->data = UA_malloc(1)))
return UA_STATUSCODE_BADOUTOFMEMORY;
nonce->length = 1;
nonce->data[0] = 'a';
return UA_STATUSCODE_GOOD;
}
#if (__GNUC__ >= 4 && __GNUC_MINOR__ >= 6)
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wextra"
#pragma GCC diagnostic ignored "-Wcast-qual"
#pragma GCC diagnostic ignored "-Wunused-value"
#endif
void UA_SecureChannel_attachSession(UA_SecureChannel *channel, UA_Session *session) {
struct SessionEntry *se = UA_malloc(sizeof(struct SessionEntry));
if(!se)
return;
se->session = session;
#ifdef UA_ENABLE_MULTITHREADING
if(uatomic_cmpxchg(&session->channel, NULL, channel) != NULL) {
UA_free(se);
return;
}
#else
if(session->channel != NULL) {
UA_free(se);
return;
}
session->channel = channel;
#endif
LIST_INSERT_HEAD(&channel->sessions, se, pointers);
}
#if (__GNUC__ >= 4 && __GNUC_MINOR__ >= 6)
#pragma GCC diagnostic pop
#endif
void UA_SecureChannel_detachSession(UA_SecureChannel *channel, UA_Session *session) {
if(session)
session->channel = NULL;
struct SessionEntry *se, *temp;
LIST_FOREACH_SAFE(se, &channel->sessions, pointers, temp) {
if(se->session != session)
continue;
LIST_REMOVE(se, pointers);
UA_free(se);
break;
}
}
UA_Session * UA_SecureChannel_getSession(UA_SecureChannel *channel, UA_NodeId *token) {
struct SessionEntry *se;
LIST_FOREACH(se, &channel->sessions, pointers) {
if(UA_NodeId_equal(&se->session->authenticationToken, token))
break;
}
if(!se)
return NULL;
return se->session;
}
void UA_SecureChannel_revolveTokens(UA_SecureChannel *channel) {
if(channel->nextSecurityToken.tokenId == 0) //no security token issued
return;
//FIXME: not thread-safe
memcpy(&channel->securityToken, &channel->nextSecurityToken, sizeof(UA_ChannelSecurityToken));
UA_ChannelSecurityToken_init(&channel->nextSecurityToken);
}
static UA_StatusCode
UA_SecureChannel_sendChunk(UA_ChunkInfo *ci, UA_ByteString *dst, size_t offset) {
UA_SecureChannel *channel = ci->channel;
UA_Connection *connection = channel->connection;
if(!connection)
return UA_STATUSCODE_BADINTERNALERROR;
/* adjust the buffer where the header was hidden */
dst->data = &dst->data[-UA_SECURE_MESSAGE_HEADER_LENGTH];
dst->length += UA_SECURE_MESSAGE_HEADER_LENGTH;
offset += UA_SECURE_MESSAGE_HEADER_LENGTH;
ci->messageSizeSoFar += offset;
UA_Boolean chunkedMsg = (ci->chunksSoFar > 0 || ci->final == false);
UA_Boolean abortMsg = ((++ci->chunksSoFar >= connection->remoteConf.maxChunkCount ||
ci->messageSizeSoFar > connection->remoteConf.maxMessageSize)) && chunkedMsg;
/* Prepare the chunk headers */
UA_SecureConversationMessageHeader respHeader;
respHeader.secureChannelId = channel->securityToken.channelId;
respHeader.messageHeader.messageTypeAndChunkType = ci->messageType;
if(!abortMsg) {
if(ci->final)
respHeader.messageHeader.messageTypeAndChunkType += UA_CHUNKTYPE_FINAL;
else
respHeader.messageHeader.messageTypeAndChunkType += UA_CHUNKTYPE_INTERMEDIATE;
} else {
respHeader.messageHeader.messageTypeAndChunkType += UA_CHUNKTYPE_ABORT;
ci->abort = true;
UA_StatusCode retval = UA_STATUSCODE_BADTCPMESSAGETOOLARGE;
UA_String errorMsg = UA_STRING("Encoded message too long");
offset = UA_SECURE_MESSAGE_HEADER_LENGTH;
UA_UInt32_encodeBinary(&retval,dst,&offset);
UA_String_encodeBinary(&errorMsg,dst,&offset);
}
respHeader.messageHeader.messageSize = (UA_UInt32)offset;
UA_SymmetricAlgorithmSecurityHeader symSecHeader;
symSecHeader.tokenId = channel->securityToken.tokenId;
UA_SequenceHeader seqHeader;
seqHeader.requestId = ci->requestId;
#ifndef UA_ENABLE_MULTITHREADING
seqHeader.sequenceNumber = ++channel->sequenceNumber;
#else
seqHeader.sequenceNumber = uatomic_add_return(&channel->sequenceNumber, 1);
#endif
/* Encode the header at the beginning of the buffer */
size_t offset_header = 0;
UA_SecureConversationMessageHeader_encodeBinary(&respHeader, dst, &offset_header);
UA_SymmetricAlgorithmSecurityHeader_encodeBinary(&symSecHeader, dst, &offset_header);
UA_SequenceHeader_encodeBinary(&seqHeader, dst, &offset_header);
/* Send the chunk, the buffer is freed in the network layer */
dst->length = offset; /* set the buffer length to the content length */
connection->send(channel->connection, dst);
/* Replace with the buffer for the next chunk */
if(!ci->final && !ci->abort) {
UA_StatusCode retval = connection->getSendBuffer(connection, connection->localConf.sendBufferSize, dst);
if(retval != UA_STATUSCODE_GOOD)
return retval;
/* Hide the header of the buffer, so that the ensuing encoding does not overwrite anything */
dst->data = &dst->data[UA_SECURE_MESSAGE_HEADER_LENGTH];
dst->length = connection->localConf.sendBufferSize - UA_SECURE_MESSAGE_HEADER_LENGTH;
}
return UA_STATUSCODE_GOOD;
}
UA_StatusCode
UA_SecureChannel_sendBinaryMessage(UA_SecureChannel *channel, UA_UInt32 requestId, const void *content,
const UA_DataType *contentType) {
UA_Connection *connection = channel->connection;
if(!connection)
return UA_STATUSCODE_BADINTERNALERROR;
/* Allocate the message buffer */
UA_ByteString message;
UA_StatusCode retval = connection->getSendBuffer(connection, connection->localConf.sendBufferSize, &message);
if(retval != UA_STATUSCODE_GOOD)
return retval;
/* Hide the message beginning where the header will be encoded */
message.data = &message.data[UA_SECURE_MESSAGE_HEADER_LENGTH];
message.length -= UA_SECURE_MESSAGE_HEADER_LENGTH;
/* Encode the message type */
size_t messagePos = 0;
UA_NodeId typeId = contentType->typeId; /* always numeric */
typeId.identifier.numeric += UA_ENCODINGOFFSET_BINARY;
UA_NodeId_encodeBinary(&typeId, &message, &messagePos);
/* Encode with the chunking callback */
UA_ChunkInfo ci;
ci.channel = channel;
ci.requestId = requestId;
ci.chunksSoFar = 0;
ci.messageSizeSoFar = 0;
ci.final = false;
ci.messageType = UA_MESSAGETYPE_MSG;
ci.abort = false;
if(typeId.identifier.numeric == 446 || typeId.identifier.numeric == 449)
ci.messageType = UA_MESSAGETYPE_OPN;
else if(typeId.identifier.numeric == 452 || typeId.identifier.numeric == 455)
ci.messageType = UA_MESSAGETYPE_CLO;
retval = UA_encodeBinary(content, contentType, (UA_exchangeEncodeBuffer)UA_SecureChannel_sendChunk,
&ci, &message, &messagePos);
/* Abort message was sent, the buffer is already freed */
if(ci.abort)
return retval;
/* Encoding failed, release the message */
if(retval != UA_STATUSCODE_GOOD) {
/* Unhide the beginning of the buffer (header) */
message.data = &message.data[-UA_SECURE_MESSAGE_HEADER_LENGTH];
connection->releaseSendBuffer(connection, &message);
return retval;
}
/* Encoding finished, send the final chunk */
ci.final = UA_TRUE;
return UA_SecureChannel_sendChunk(&ci, &message, messagePos);
}
/*********************************** amalgamated original file "/home/wn/Sources/open62541-open62541-395ce48/src/ua_session.c" ***********************************/
#ifdef UA_ENABLE_SUBSCRIPTIONS
#endif
UA_Session adminSession = {
.clientDescription = {.applicationUri = {0, NULL}, .productUri = {0, NULL},
.applicationName = {.locale = {0, NULL}, .text = {0, NULL}},
.applicationType = UA_APPLICATIONTYPE_CLIENT,
.gatewayServerUri = {0, NULL}, .discoveryProfileUri = {0, NULL},
.discoveryUrlsSize = 0, .discoveryUrls = NULL},
.sessionName = {sizeof("Administrator Session")-1, (UA_Byte*)"Administrator Session"},
.authenticationToken = {.namespaceIndex = 0, .identifierType = UA_NODEIDTYPE_NUMERIC,
.identifier.numeric = 1},
.sessionId = {.namespaceIndex = 0, .identifierType = UA_NODEIDTYPE_NUMERIC, .identifier.numeric = 1},
.maxRequestMessageSize = UA_UINT32_MAX, .maxResponseMessageSize = UA_UINT32_MAX,
.timeout = (UA_Double)UA_INT64_MAX, .validTill = UA_INT64_MAX, .channel = NULL,
.continuationPoints = {NULL}};
void UA_Session_init(UA_Session *session) {
UA_ApplicationDescription_init(&session->clientDescription);
session->activated = false;
UA_NodeId_init(&session->authenticationToken);
UA_NodeId_init(&session->sessionId);
UA_String_init(&session->sessionName);
session->maxRequestMessageSize = 0;
session->maxResponseMessageSize = 0;
session->timeout = 0;
UA_DateTime_init(&session->validTill);
session->channel = NULL;
session->availableContinuationPoints = MAXCONTINUATIONPOINTS;
LIST_INIT(&session->continuationPoints);
#ifdef UA_ENABLE_SUBSCRIPTIONS
LIST_INIT(&session->serverSubscriptions);
session->lastSubscriptionID = UA_UInt32_random();
SIMPLEQ_INIT(&session->responseQueue);
#endif
}
void UA_Session_deleteMembersCleanup(UA_Session *session, UA_Server* server) {
UA_ApplicationDescription_deleteMembers(&session->clientDescription);
UA_NodeId_deleteMembers(&session->authenticationToken);
UA_NodeId_deleteMembers(&session->sessionId);
UA_String_deleteMembers(&session->sessionName);
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);
}
if(session->channel)
UA_SecureChannel_detachSession(session->channel, session);
#ifdef UA_ENABLE_SUBSCRIPTIONS
UA_Subscription *currents, *temps;
LIST_FOREACH_SAFE(currents, &session->serverSubscriptions, listEntry, temps) {
LIST_REMOVE(currents, listEntry);
UA_Subscription_deleteMembers(currents, server);
UA_free(currents);
}
UA_PublishResponseEntry *entry;
while((entry = SIMPLEQ_FIRST(&session->responseQueue))) {
SIMPLEQ_REMOVE_HEAD(&session->responseQueue, listEntry);
UA_PublishResponse_deleteMembers(&entry->response);
UA_free(entry);
}
#endif
}
void UA_Session_updateLifetime(UA_Session *session) {
session->validTill = UA_DateTime_now() + (UA_DateTime)(session->timeout * UA_MSEC_TO_DATETIME);
}
#ifdef UA_ENABLE_SUBSCRIPTIONS
void UA_Session_addSubscription(UA_Session *session, UA_Subscription *newSubscription) {
LIST_INSERT_HEAD(&session->serverSubscriptions, newSubscription, listEntry);
}
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;
LIST_REMOVE(sub, listEntry);
UA_Subscription_deleteMembers(sub, server);
UA_free(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_UInt32 UA_Session_getUniqueSubscriptionID(UA_Session *session) {
return ++(session->lastSubscriptionID);
}
#endif
/*********************************** amalgamated original file "/home/wn/Sources/open62541-open62541-395ce48/src/server/ua_server.c" ***********************************/
#ifdef UA_ENABLE_GENERATE_NAMESPACE0
#endif
#if defined(UA_ENABLE_MULTITHREADING) && !defined(NDEBUG)
UA_THREAD_LOCAL bool rcu_locked = false;
#endif
static const UA_NodeId nodeIdHasSubType = {
.namespaceIndex = 0, .identifierType = UA_NODEIDTYPE_NUMERIC,
.identifier.numeric = UA_NS0ID_HASSUBTYPE};
static const UA_NodeId nodeIdHasTypeDefinition = {
.namespaceIndex = 0, .identifierType = UA_NODEIDTYPE_NUMERIC,
.identifier.numeric = UA_NS0ID_HASTYPEDEFINITION};
static const UA_NodeId nodeIdHasComponent = {
.namespaceIndex = 0, .identifierType = UA_NODEIDTYPE_NUMERIC,
.identifier.numeric = UA_NS0ID_HASCOMPONENT};
static const UA_NodeId nodeIdHasProperty = {
.namespaceIndex = 0, .identifierType = UA_NODEIDTYPE_NUMERIC,
.identifier.numeric = UA_NS0ID_HASPROPERTY};
static const UA_NodeId nodeIdOrganizes = {
.namespaceIndex = 0, .identifierType = UA_NODEIDTYPE_NUMERIC,
.identifier.numeric = UA_NS0ID_ORGANIZES};
static const UA_ExpandedNodeId expandedNodeIdBaseDataVariabletype = {
.nodeId = {.namespaceIndex = 0, .identifierType = UA_NODEIDTYPE_NUMERIC,
.identifier.numeric = UA_NS0ID_BASEDATAVARIABLETYPE},
.namespaceUri = {.length = 0, .data = NULL}, .serverIndex = 0};
#ifndef UA_ENABLE_GENERATE_NAMESPACE0
static const UA_NodeId nodeIdNonHierarchicalReferences = {
.namespaceIndex = 0, .identifierType = UA_NODEIDTYPE_NUMERIC,
.identifier.numeric = UA_NS0ID_NONHIERARCHICALREFERENCES};
#endif
/**********************/
/* Namespace Handling */
/**********************/
#ifdef UA_ENABLE_EXTERNAL_NAMESPACES
static void UA_ExternalNamespace_init(UA_ExternalNamespace *ens) {
ens->index = 0;
UA_String_init(&ens->url);
}
static void UA_ExternalNamespace_deleteMembers(UA_ExternalNamespace *ens) {
UA_String_deleteMembers(&ens->url);
ens->externalNodeStore.destroy(ens->externalNodeStore.ensHandle);
}
static void UA_Server_deleteExternalNamespaces(UA_Server *server) {
for(UA_UInt32 i = 0; i < server->externalNamespacesSize; i++){
UA_ExternalNamespace_deleteMembers(&(server->externalNamespaces[i]));
}
if(server->externalNamespacesSize > 0){
UA_free(server->externalNamespaces);
server->externalNamespaces = NULL;
server->externalNamespacesSize = 0;
}
}
UA_StatusCode UA_EXPORT
UA_Server_addExternalNamespace(UA_Server *server,
const UA_String *url, UA_ExternalNodeStore *nodeStore,UA_UInt16 *assignedNamespaceIndex) {
if (nodeStore == NULL)
return UA_STATUSCODE_BADARGUMENTSMISSING;
UA_UInt32 size = server->externalNamespacesSize;
server->externalNamespaces =
UA_realloc(server->externalNamespaces, sizeof(UA_ExternalNamespace) * (size + 1));
server->externalNamespaces[size].externalNodeStore = *nodeStore;
server->externalNamespaces[size].index = server->namespacesSize;
*assignedNamespaceIndex = server->namespacesSize;
UA_String_copy(url, &server->externalNamespaces[size].url);
server->externalNamespacesSize++;
UA_Server_addNamespace(server, url);
return UA_STATUSCODE_GOOD;
}
#endif /* UA_ENABLE_EXTERNAL_NAMESPACES*/
static UA_UInt16 addNamespaceInternal(UA_Server *server, 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;
}
//the namespace URI did not match - add a new namespace to the namsepace array
server->namespaces = UA_realloc(server->namespaces,
sizeof(UA_String) * (server->namespacesSize + 1));
UA_String_copy(name, &(server->namespaces[server->namespacesSize]));
server->namespacesSize++;
return (UA_UInt16)(server->namespacesSize - 1);
}
UA_UInt16 UA_Server_addNamespace(UA_Server *server, const char* name) {
UA_String nameString = UA_STRING_ALLOC(name);
return addNamespaceInternal(server, &nameString);
}
UA_StatusCode
UA_Server_deleteNode(UA_Server *server, const UA_NodeId nodeId, UA_Boolean deleteReferences) {
UA_RCU_LOCK();
UA_StatusCode retval = Service_DeleteNodes_single(server, &adminSession, &nodeId, deleteReferences);
UA_RCU_UNLOCK();
return retval;
}
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_RCU_LOCK();
UA_StatusCode retval = Service_DeleteReferences_single(server, &adminSession, &item);
UA_RCU_UNLOCK();
return retval;
}
UA_StatusCode
UA_Server_forEachChildNodeCall(UA_Server *server, UA_NodeId parentNodeId,
UA_NodeIteratorCallback callback, void *handle) {
UA_StatusCode retval = UA_STATUSCODE_GOOD;
UA_RCU_LOCK();
const UA_Node *parent = UA_NodeStore_get(server->nodestore, &parentNodeId);
if(!parent) {
UA_RCU_UNLOCK();
return UA_STATUSCODE_BADNODEIDINVALID;
}
for(size_t i = 0; i < parent->referencesSize; i++) {
UA_ReferenceNode *ref = &parent->references[i];
retval |= callback(ref->targetId.nodeId, ref->isInverse,
ref->referenceTypeId, handle);
}
UA_RCU_UNLOCK();
return retval;
}
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_RCU_LOCK();
UA_StatusCode retval = Service_AddReferences_single(server, &adminSession, &item);
UA_RCU_UNLOCK();
return retval;
}
static UA_StatusCode
addReferenceInternal(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_RCU_LOCK();
UA_StatusCode retval = Service_AddReferences_single(server, &adminSession, &item);
UA_RCU_UNLOCK();
return retval;
}
static UA_AddNodesResult
addNodeInternal(UA_Server *server, UA_Node *node, const UA_NodeId parentNodeId,
const UA_NodeId referenceTypeId) {
UA_AddNodesResult res;
UA_AddNodesResult_init(&res);
UA_RCU_LOCK();
Service_AddNodes_existing(server, &adminSession, node, &parentNodeId,
&referenceTypeId, &res);
UA_RCU_UNLOCK();
return res;
}
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,
UA_InstantiationCallback *instantiationCallback, UA_NodeId *outNewNodeId) {
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 = (UA_ExtensionObject){.encoding = UA_EXTENSIONOBJECT_DECODED_NODELETE,
.content.decoded = {attributeType, (void*)(uintptr_t)attr}};
UA_AddNodesResult result;
UA_AddNodesResult_init(&result);
UA_RCU_LOCK();
Service_AddNodes_single(server, &adminSession, &item, &result, instantiationCallback);
UA_RCU_UNLOCK();
if(outNewNodeId && result.statusCode == UA_STATUSCODE_GOOD)
*outNewNodeId = result.addedNodeId;
else
UA_AddNodesResult_deleteMembers(&result);
return result.statusCode;
}
/**********/
/* Server */
/**********/
/* The server needs to be stopped before it can be deleted */
void UA_Server_delete(UA_Server *server) {
// Delete the timed work
UA_Server_deleteAllRepeatedJobs(server);
// Delete all internal data
UA_SecureChannelManager_deleteMembers(&server->secureChannelManager);
UA_SessionManager_deleteMembers(&server->sessionManager);
UA_RCU_LOCK();
UA_NodeStore_delete(server->nodestore);
UA_RCU_UNLOCK();
#ifdef UA_ENABLE_EXTERNAL_NAMESPACES
UA_Server_deleteExternalNamespaces(server);
#endif
UA_Array_delete(server->namespaces, server->namespacesSize, &UA_TYPES[UA_TYPES_STRING]);
UA_Array_delete(server->endpointDescriptions, server->endpointDescriptionsSize,
&UA_TYPES[UA_TYPES_ENDPOINTDESCRIPTION]);
#ifdef UA_ENABLE_MULTITHREADING
pthread_cond_destroy(&server->dispatchQueue_condition);
#endif
UA_free(server);
}
/* Recurring cleanup. Removing unused and timed-out channels and sessions */
static void UA_Server_cleanup(UA_Server *server, void *_) {
UA_DateTime now = UA_DateTime_now();
UA_SessionManager_cleanupTimedOut(&server->sessionManager, now);
UA_SecureChannelManager_cleanupTimedOut(&server->secureChannelManager, now);
}
static UA_StatusCode
readStatus(void *handle, const UA_NodeId nodeid, 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_Server *server = (UA_Server*)handle;
UA_ServerStatusDataType *status = UA_ServerStatusDataType_new();
status->startTime = server->startTime;
status->currentTime = UA_DateTime_now();
status->state = UA_SERVERSTATE_RUNNING;
status->secondsTillShutdown = 0;
value->value.type = &UA_TYPES[UA_TYPES_SERVERSTATUSDATATYPE];
value->value.arrayLength = 0;
value->value.data = status;
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
readNamespaces(void *handle, const UA_NodeId nodeid, 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_Server *server = (UA_Server*)handle;
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(sourceTimestamp) {
value->hasSourceTimestamp = true;
value->sourceTimestamp = UA_DateTime_now();
}
return UA_STATUSCODE_GOOD;
}
static UA_StatusCode
readCurrentTime(void *handle, const UA_NodeId nodeid, 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;
}
static void copyNames(UA_Node *node, char *name) {
node->browseName = UA_QUALIFIEDNAME_ALLOC(0, name);
node->displayName = UA_LOCALIZEDTEXT_ALLOC("en_US", name);
node->description = UA_LOCALIZEDTEXT_ALLOC("en_US", name);
}
static void
addDataTypeNode(UA_Server *server, char* name, UA_UInt32 datatypeid, UA_UInt32 parent) {
UA_DataTypeNode *datatype = UA_NodeStore_newDataTypeNode();
copyNames((UA_Node*)datatype, name);
datatype->nodeId.identifier.numeric = datatypeid;
addNodeInternal(server, (UA_Node*)datatype, UA_NODEID_NUMERIC(0, parent), nodeIdOrganizes);
}
static void
addObjectTypeNode(UA_Server *server, char* name, UA_UInt32 objecttypeid,
UA_UInt32 parent, UA_UInt32 parentreference) {
UA_ObjectTypeNode *objecttype = UA_NodeStore_newObjectTypeNode();
copyNames((UA_Node*)objecttype, name);
objecttype->nodeId.identifier.numeric = objecttypeid;
addNodeInternal(server, (UA_Node*)objecttype, UA_NODEID_NUMERIC(0, parent),
UA_NODEID_NUMERIC(0, parentreference));
}
static UA_VariableTypeNode*
createVariableTypeNode(UA_Server *server, char* name, UA_UInt32 variabletypeid,
UA_UInt32 parent, UA_Boolean abstract) {
UA_VariableTypeNode *variabletype = UA_NodeStore_newVariableTypeNode();
copyNames((UA_Node*)variabletype, name);
variabletype->nodeId.identifier.numeric = variabletypeid;
variabletype->isAbstract = abstract;
variabletype->value.variant.value.type = &UA_TYPES[UA_TYPES_VARIANT];
return variabletype;
}
static void
addVariableTypeNode_organized(UA_Server *server, char* name, UA_UInt32 variabletypeid,
UA_UInt32 parent, UA_Boolean abstract) {
UA_VariableTypeNode *variabletype = createVariableTypeNode(server, name, variabletypeid, parent, abstract);
addNodeInternal(server, (UA_Node*)variabletype, UA_NODEID_NUMERIC(0, parent), nodeIdOrganizes);
}
static void
addVariableTypeNode_subtype(UA_Server *server, char* name, UA_UInt32 variabletypeid,
UA_UInt32 parent, UA_Boolean abstract) {
UA_VariableTypeNode *variabletype =
createVariableTypeNode(server, name, variabletypeid, parent, abstract);
addNodeInternal(server, (UA_Node*)variabletype, UA_NODEID_NUMERIC(0, parent), nodeIdHasSubType);
}
UA_Server * UA_Server_new(const UA_ServerConfig config) {
UA_Server *server = UA_calloc(1, sizeof(UA_Server));
if(!server)
return NULL;
server->config = config;
server->nodestore = UA_NodeStore_new();
LIST_INIT(&server->repeatedJobs);
#ifdef UA_ENABLE_MULTITHREADING
rcu_init();
cds_wfcq_init(&server->dispatchQueue_head, &server->dispatchQueue_tail);
cds_lfs_init(&server->mainLoopJobs);
#endif
/* uncomment for non-reproducible server runs */
//UA_random_seed(UA_DateTime_now());
/* ns0 and ns1 */
server->namespaces = 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;
server->endpointDescriptions = UA_Array_new(server->config.networkLayersSize,
&UA_TYPES[UA_TYPES_ENDPOINTDESCRIPTION]);
server->endpointDescriptionsSize = server->config.networkLayersSize;
for(size_t i = 0; i < server->config.networkLayersSize; i++) {
UA_EndpointDescription *endpoint = &server->endpointDescriptions[i];
endpoint->securityMode = UA_MESSAGESECURITYMODE_NONE;
endpoint->securityPolicyUri =
UA_STRING_ALLOC("http://opcfoundation.org/UA/SecurityPolicy#None");
endpoint->transportProfileUri =
UA_STRING_ALLOC("http://opcfoundation.org/UA-Profile/Transport/uatcp-uasc-uabinary");
size_t policies = 0;
if(server->config.enableAnonymousLogin)
policies++;
if(server->config.enableUsernamePasswordLogin)
policies++;
endpoint->userIdentityTokensSize = policies;
endpoint->userIdentityTokens = UA_Array_new(policies, &UA_TYPES[UA_TYPES_USERTOKENPOLICY]);
size_t currentIndex = 0;
if(server->config.enableAnonymousLogin) {
UA_UserTokenPolicy_init(&endpoint->userIdentityTokens[currentIndex]);
endpoint->userIdentityTokens[currentIndex].tokenType = UA_USERTOKENTYPE_ANONYMOUS;
endpoint->userIdentityTokens[currentIndex].policyId = UA_STRING_ALLOC(ANONYMOUS_POLICY);
currentIndex++;
}
if(server->config.enableUsernamePasswordLogin) {
UA_UserTokenPolicy_init(&endpoint->userIdentityTokens[currentIndex]);
endpoint->userIdentityTokens[currentIndex].tokenType = UA_USERTOKENTYPE_USERNAME;
endpoint->userIdentityTokens[currentIndex].policyId = UA_STRING_ALLOC(USERNAME_POLICY);
}
/* The standard says "the HostName specified in the Server Certificate is the
same as the HostName contained in the endpointUrl provided in the
EndpointDescription */
UA_String_copy(&server->config.serverCertificate, &endpoint->serverCertificate);
UA_ApplicationDescription_copy(&server->config.applicationDescription, &endpoint->server);
/* copy the discovery url only once the networlayer has been started */
// UA_String_copy(&server->config.networkLayers[i].discoveryUrl, &endpoint->endpointUrl);
}
#define MAXCHANNELCOUNT 100
#define STARTCHANNELID 1
#define TOKENLIFETIME 600000 //this is in milliseconds //600000 seems to be the minimal allowet time for UaExpert
#define STARTTOKENID 1
UA_SecureChannelManager_init(&server->secureChannelManager, MAXCHANNELCOUNT,
TOKENLIFETIME, STARTCHANNELID, STARTTOKENID, server);
#define MAXSESSIONCOUNT 1000
#define MAXSESSIONLIFETIME 3600000
#define STARTSESSIONID 1
UA_SessionManager_init(&server->sessionManager, MAXSESSIONCOUNT, MAXSESSIONLIFETIME,
STARTSESSIONID, server);
UA_Job cleanup = {.type = UA_JOBTYPE_METHODCALL,
.job.methodCall = {.method = UA_Server_cleanup, .data = NULL} };
UA_Server_addRepeatedJob(server, cleanup, 10000, NULL);
/**********************/
/* Server Information */
/**********************/
server->startTime = UA_DateTime_now();
/**************/
/* References */
/**************/
#ifndef UA_ENABLE_GENERATE_NAMESPACE0
/* Bootstrap by manually inserting "references" and "hassubtype" */
UA_ReferenceTypeNode *references = UA_NodeStore_newReferenceTypeNode();
copyNames((UA_Node*)references, "References");
references->nodeId.identifier.numeric = UA_NS0ID_REFERENCES;
references->isAbstract = true;
references->symmetric = true;
references->inverseName = UA_LOCALIZEDTEXT_ALLOC("en_US", "References");
/* The reference to root is later inserted */
UA_RCU_LOCK();
UA_NodeStore_insert(server->nodestore, (UA_Node*)references);
UA_RCU_UNLOCK();
UA_ReferenceTypeNode *hassubtype = UA_NodeStore_newReferenceTypeNode();
copyNames((UA_Node*)hassubtype, "HasSubtype");
hassubtype->inverseName = UA_LOCALIZEDTEXT_ALLOC("en_US", "HasSupertype");
hassubtype->nodeId.identifier.numeric = UA_NS0ID_HASSUBTYPE;
hassubtype->isAbstract = false;
hassubtype->symmetric = false;
/* The reference to root is later inserted */
UA_RCU_LOCK();
UA_NodeStore_insert(server->nodestore, (UA_Node*)hassubtype);
UA_RCU_UNLOCK();
/* Continue adding reference types with normal "addnode" */
UA_ReferenceTypeNode *hierarchicalreferences = UA_NodeStore_newReferenceTypeNode();
copyNames((UA_Node*)hierarchicalreferences, "Hierarchicalreferences");
hierarchicalreferences->nodeId.identifier.numeric = UA_NS0ID_HIERARCHICALREFERENCES;
hierarchicalreferences->isAbstract = true;
hierarchicalreferences->symmetric = false;
addNodeInternal(server, (UA_Node*)hierarchicalreferences,
UA_NODEID_NUMERIC(0, UA_NS0ID_REFERENCES), nodeIdHasSubType);
UA_ReferenceTypeNode *nonhierarchicalreferences = UA_NodeStore_newReferenceTypeNode();
copyNames((UA_Node*)nonhierarchicalreferences, "NonHierarchicalReferences");
nonhierarchicalreferences->nodeId.identifier.numeric = UA_NS0ID_NONHIERARCHICALREFERENCES;
nonhierarchicalreferences->isAbstract = true;
nonhierarchicalreferences->symmetric = false;
addNodeInternal(server, (UA_Node*)nonhierarchicalreferences,
UA_NODEID_NUMERIC(0, UA_NS0ID_REFERENCES), nodeIdHasSubType);
UA_ReferenceTypeNode *haschild = UA_NodeStore_newReferenceTypeNode();
copyNames((UA_Node*)haschild, "HasChild");
haschild->nodeId.identifier.numeric = UA_NS0ID_HASCHILD;
haschild->isAbstract = true;
haschild->symmetric = false;
addNodeInternal(server, (UA_Node*)haschild,
UA_NODEID_NUMERIC(0, UA_NS0ID_HIERARCHICALREFERENCES), nodeIdHasSubType);
UA_ReferenceTypeNode *organizes = UA_NodeStore_newReferenceTypeNode();
copyNames((UA_Node*)organizes, "Organizes");
organizes->inverseName = UA_LOCALIZEDTEXT_ALLOC("en_US", "OrganizedBy");
organizes->nodeId.identifier.numeric = UA_NS0ID_ORGANIZES;
organizes->isAbstract = false;
organizes->symmetric = false;
addNodeInternal(server, (UA_Node*)organizes,
UA_NODEID_NUMERIC(0, UA_NS0ID_HIERARCHICALREFERENCES), nodeIdHasSubType);
UA_ReferenceTypeNode *haseventsource = UA_NodeStore_newReferenceTypeNode();
copyNames((UA_Node*)haseventsource, "HasEventSource");
haseventsource->inverseName = UA_LOCALIZEDTEXT_ALLOC("en_US", "EventSourceOf");
haseventsource->nodeId.identifier.numeric = UA_NS0ID_HASEVENTSOURCE;
haseventsource->isAbstract = false;
haseventsource->symmetric = false;
addNodeInternal(server, (UA_Node*)haseventsource,
UA_NODEID_NUMERIC(0, UA_NS0ID_HIERARCHICALREFERENCES), nodeIdHasSubType);
UA_ReferenceTypeNode *hasmodellingrule = UA_NodeStore_newReferenceTypeNode();
copyNames((UA_Node*)hasmodellingrule, "HasModellingRule");
hasmodellingrule->inverseName = UA_LOCALIZEDTEXT_ALLOC("en_US", "ModellingRuleOf");
hasmodellingrule->nodeId.identifier.numeric = UA_NS0ID_HASMODELLINGRULE;
hasmodellingrule->isAbstract = false;
hasmodellingrule->symmetric = false;
addNodeInternal(server, (UA_Node*)hasmodellingrule, nodeIdNonHierarchicalReferences, nodeIdHasSubType);
UA_ReferenceTypeNode *hasencoding = UA_NodeStore_newReferenceTypeNode();
copyNames((UA_Node*)hasencoding, "HasEncoding");
hasencoding->inverseName = UA_LOCALIZEDTEXT_ALLOC("en_US", "EncodingOf");
hasencoding->nodeId.identifier.numeric = UA_NS0ID_HASENCODING;
hasencoding->isAbstract = false;
hasencoding->symmetric = false;
addNodeInternal(server, (UA_Node*)hasencoding, nodeIdNonHierarchicalReferences, nodeIdHasSubType);
UA_ReferenceTypeNode *hasdescription = UA_NodeStore_newReferenceTypeNode();
copyNames((UA_Node*)hasdescription, "HasDescription");
hasdescription->inverseName = UA_LOCALIZEDTEXT_ALLOC("en_US", "DescriptionOf");
hasdescription->nodeId.identifier.numeric = UA_NS0ID_HASDESCRIPTION;
hasdescription->isAbstract = false;
hasdescription->symmetric = false;
addNodeInternal(server, (UA_Node*)hasdescription, nodeIdNonHierarchicalReferences, nodeIdHasSubType);
UA_ReferenceTypeNode *hastypedefinition = UA_NodeStore_newReferenceTypeNode();
copyNames((UA_Node*)hastypedefinition, "HasTypeDefinition");
hastypedefinition->inverseName = UA_LOCALIZEDTEXT_ALLOC("en_US", "TypeDefinitionOf");
hastypedefinition->nodeId.identifier.numeric = UA_NS0ID_HASTYPEDEFINITION;
hastypedefinition->isAbstract = false;
hastypedefinition->symmetric = false;
addNodeInternal(server, (UA_Node*)hastypedefinition, nodeIdNonHierarchicalReferences, nodeIdHasSubType);
UA_ReferenceTypeNode *generatesevent = UA_NodeStore_newReferenceTypeNode();
copyNames((UA_Node*)generatesevent, "GeneratesEvent");
generatesevent->inverseName = UA_LOCALIZEDTEXT_ALLOC("en_US", "GeneratedBy");
generatesevent->nodeId.identifier.numeric = UA_NS0ID_GENERATESEVENT;
generatesevent->isAbstract = false;
generatesevent->symmetric = false;
addNodeInternal(server, (UA_Node*)generatesevent, nodeIdNonHierarchicalReferences,
nodeIdHasSubType);
UA_ReferenceTypeNode *aggregates = UA_NodeStore_newReferenceTypeNode();
copyNames((UA_Node*)aggregates, "Aggregates");
// Todo: Is there an inverse name?
aggregates->nodeId.identifier.numeric = UA_NS0ID_AGGREGATES;
aggregates->isAbstract = true;
aggregates->symmetric = false;
addNodeInternal(server, (UA_Node*)aggregates,
UA_NODEID_NUMERIC(0, UA_NS0ID_HASCHILD), nodeIdHasSubType);
// complete bootstrap of hassubtype
addReferenceInternal(server, UA_NODEID_NUMERIC(0, UA_NS0ID_HASCHILD), nodeIdHasSubType,
UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_HASSUBTYPE), true);
UA_ReferenceTypeNode *hasproperty = UA_NodeStore_newReferenceTypeNode();
copyNames((UA_Node*)hasproperty, "HasProperty");
hasproperty->inverseName = UA_LOCALIZEDTEXT_ALLOC("en_US", "PropertyOf");
hasproperty->nodeId.identifier.numeric = UA_NS0ID_HASPROPERTY;
hasproperty->isAbstract = false;
hasproperty->symmetric = false;
addNodeInternal(server, (UA_Node*)hasproperty,
UA_NODEID_NUMERIC(0, UA_NS0ID_AGGREGATES), nodeIdHasSubType);
UA_ReferenceTypeNode *hascomponent = UA_NodeStore_newReferenceTypeNode();
copyNames((UA_Node*)hascomponent, "HasComponent");
hascomponent->inverseName = UA_LOCALIZEDTEXT_ALLOC("en_US", "ComponentOf");
hascomponent->nodeId.identifier.numeric = UA_NS0ID_HASCOMPONENT;
hascomponent->isAbstract = false;
hascomponent->symmetric = false;
addNodeInternal(server, (UA_Node*)hascomponent,
UA_NODEID_NUMERIC(0, UA_NS0ID_AGGREGATES), nodeIdHasSubType);
UA_ReferenceTypeNode *hasnotifier = UA_NodeStore_newReferenceTypeNode();
copyNames((UA_Node*)hasnotifier, "HasNotifier");
hasnotifier->inverseName = UA_LOCALIZEDTEXT_ALLOC("en_US", "NotifierOf");
hasnotifier->nodeId.identifier.numeric = UA_NS0ID_HASNOTIFIER;
hasnotifier->isAbstract = false;
hasnotifier->symmetric = false;
addNodeInternal(server, (UA_Node*)hasnotifier, UA_NODEID_NUMERIC(0, UA_NS0ID_HASEVENTSOURCE),
nodeIdHasSubType);
UA_ReferenceTypeNode *hasorderedcomponent = UA_NodeStore_newReferenceTypeNode();
copyNames((UA_Node*)hasorderedcomponent, "HasOrderedComponent");
hasorderedcomponent->inverseName = UA_LOCALIZEDTEXT_ALLOC("en_US", "OrderedComponentOf");
hasorderedcomponent->nodeId.identifier.numeric = UA_NS0ID_HASORDEREDCOMPONENT;
hasorderedcomponent->isAbstract = false;
hasorderedcomponent->symmetric = false;
addNodeInternal(server, (UA_Node*)hasorderedcomponent, UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT),
nodeIdHasSubType);
UA_ReferenceTypeNode *hasmodelparent = UA_NodeStore_newReferenceTypeNode();
copyNames((UA_Node*)hasmodelparent, "HasModelParent");
hasmodelparent->inverseName = UA_LOCALIZEDTEXT_ALLOC("en_US", "ModelParentOf");
hasmodelparent->nodeId.identifier.numeric = UA_NS0ID_HASMODELPARENT;
hasmodelparent->isAbstract = false;
hasmodelparent->symmetric = false;
addNodeInternal(server, (UA_Node*)hasmodelparent, nodeIdNonHierarchicalReferences, nodeIdHasSubType);
UA_ReferenceTypeNode *fromstate = UA_NodeStore_newReferenceTypeNode();
copyNames((UA_Node*)fromstate, "FromState");
fromstate->inverseName = UA_LOCALIZEDTEXT_ALLOC("en_US", "ToTransition");
fromstate->nodeId.identifier.numeric = UA_NS0ID_FROMSTATE;
fromstate->isAbstract = false;
fromstate->symmetric = false;
addNodeInternal(server, (UA_Node*)fromstate, nodeIdNonHierarchicalReferences, nodeIdHasSubType);
UA_ReferenceTypeNode *tostate = UA_NodeStore_newReferenceTypeNode();
copyNames((UA_Node*)tostate, "ToState");
tostate->inverseName = UA_LOCALIZEDTEXT_ALLOC("en_US", "FromTransition");
tostate->nodeId.identifier.numeric = UA_NS0ID_TOSTATE;
tostate->isAbstract = false;
tostate->symmetric = false;
addNodeInternal(server, (UA_Node*)tostate, nodeIdNonHierarchicalReferences, nodeIdHasSubType);
UA_ReferenceTypeNode *hascause = UA_NodeStore_newReferenceTypeNode();
copyNames((UA_Node*)hascause, "HasCause");
hascause->inverseName = UA_LOCALIZEDTEXT_ALLOC("en_US", "MayBeCausedBy");
hascause->nodeId.identifier.numeric = UA_NS0ID_HASCAUSE;
hascause->isAbstract = false;
hascause->symmetric = false;
addNodeInternal(server, (UA_Node*)hascause, nodeIdNonHierarchicalReferences, nodeIdHasSubType);
UA_ReferenceTypeNode *haseffect = UA_NodeStore_newReferenceTypeNode();
copyNames((UA_Node*)haseffect, "HasEffect");
haseffect->inverseName = UA_LOCALIZEDTEXT_ALLOC("en_US", "MayBeEffectedBy");
haseffect->nodeId.identifier.numeric = UA_NS0ID_HASEFFECT;
haseffect->isAbstract = false;
haseffect->symmetric = false;
addNodeInternal(server, (UA_Node*)haseffect, nodeIdNonHierarchicalReferences, nodeIdHasSubType);
UA_ReferenceTypeNode *hashistoricalconfiguration = UA_NodeStore_newReferenceTypeNode();
copyNames((UA_Node*)hashistoricalconfiguration, "HasHistoricalConfiguration");
hashistoricalconfiguration->inverseName = UA_LOCALIZEDTEXT_ALLOC("en_US", "HistoricalConfigurationOf");
hashistoricalconfiguration->nodeId.identifier.numeric = UA_NS0ID_HASHISTORICALCONFIGURATION;
hashistoricalconfiguration->isAbstract = false;
hashistoricalconfiguration->symmetric = false;
addNodeInternal(server, (UA_Node*)hashistoricalconfiguration,
UA_NODEID_NUMERIC(0, UA_NS0ID_AGGREGATES), nodeIdHasSubType);
/*****************/
/* Basic Folders */
/*****************/
UA_ObjectNode *root = UA_NodeStore_newObjectNode();
copyNames((UA_Node*)root, "Root");
root->nodeId.identifier.numeric = UA_NS0ID_ROOTFOLDER;
UA_RCU_LOCK();
UA_NodeStore_insert(server->nodestore, (UA_Node*)root);
UA_RCU_UNLOCK();
UA_ObjectNode *objects = UA_NodeStore_newObjectNode();
copyNames((UA_Node*)objects, "Objects");
objects->nodeId.identifier.numeric = UA_NS0ID_OBJECTSFOLDER;
addNodeInternal(server, (UA_Node*)objects, UA_NODEID_NUMERIC(0, UA_NS0ID_ROOTFOLDER),
nodeIdOrganizes);
UA_ObjectNode *types = UA_NodeStore_newObjectNode();
copyNames((UA_Node*)types, "Types");
types->nodeId.identifier.numeric = UA_NS0ID_TYPESFOLDER;
addNodeInternal(server, (UA_Node*)types, UA_NODEID_NUMERIC(0, UA_NS0ID_ROOTFOLDER),
nodeIdOrganizes);
UA_ObjectNode *views = UA_NodeStore_newObjectNode();
copyNames((UA_Node*)views, "Views");
views->nodeId.identifier.numeric = UA_NS0ID_VIEWSFOLDER;
addNodeInternal(server, (UA_Node*)views, UA_NODEID_NUMERIC(0, UA_NS0ID_ROOTFOLDER),
nodeIdOrganizes);
UA_ObjectNode *referencetypes = UA_NodeStore_newObjectNode();
copyNames((UA_Node*)referencetypes, "ReferenceTypes");
referencetypes->nodeId.identifier.numeric = UA_NS0ID_REFERENCETYPESFOLDER;
addNodeInternal(server, (UA_Node*)referencetypes, UA_NODEID_NUMERIC(0, UA_NS0ID_TYPESFOLDER),
nodeIdOrganizes);
addReferenceInternal(server, UA_NODEID_NUMERIC(0, UA_NS0ID_REFERENCETYPESFOLDER), nodeIdOrganizes,
UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_REFERENCES), true);
/**********************/
/* Basic Object Types */
/**********************/
UA_ObjectNode *objecttypes = UA_NodeStore_newObjectNode();
copyNames((UA_Node*)objecttypes, "ObjectTypes");
objecttypes->nodeId.identifier.numeric = UA_NS0ID_OBJECTTYPESFOLDER;
addNodeInternal(server, (UA_Node*)objecttypes, UA_NODEID_NUMERIC(0, UA_NS0ID_TYPESFOLDER),
nodeIdOrganizes);
addObjectTypeNode(server, "BaseObjectType", UA_NS0ID_BASEOBJECTTYPE, UA_NS0ID_OBJECTTYPESFOLDER,
UA_NS0ID_ORGANIZES);
addObjectTypeNode(server, "FolderType", UA_NS0ID_FOLDERTYPE, UA_NS0ID_BASEOBJECTTYPE, UA_NS0ID_HASSUBTYPE);
addReferenceInternal(server, UA_NODEID_NUMERIC(0, UA_NS0ID_OBJECTTYPESFOLDER), nodeIdHasTypeDefinition,
UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_FOLDERTYPE), true);
addReferenceInternal(server, UA_NODEID_NUMERIC(0, UA_NS0ID_ROOTFOLDER), nodeIdHasTypeDefinition,
UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_FOLDERTYPE), true);
addReferenceInternal(server, UA_NODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER), nodeIdHasTypeDefinition,
UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_FOLDERTYPE), true);
addReferenceInternal(server, UA_NODEID_NUMERIC(0, UA_NS0ID_TYPESFOLDER), nodeIdHasTypeDefinition,
UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_FOLDERTYPE), true);
addReferenceInternal(server, UA_NODEID_NUMERIC(0, UA_NS0ID_VIEWSFOLDER), nodeIdHasTypeDefinition,
UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_FOLDERTYPE), true);
addReferenceInternal(server, UA_NODEID_NUMERIC(0, UA_NS0ID_REFERENCETYPESFOLDER),
nodeIdHasTypeDefinition, UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_FOLDERTYPE), true);
addObjectTypeNode(server, "ServerType", UA_NS0ID_SERVERTYPE, UA_NS0ID_BASEOBJECTTYPE, UA_NS0ID_HASSUBTYPE);
addObjectTypeNode(server, "ServerDiagnosticsType", UA_NS0ID_SERVERDIAGNOSTICSTYPE,
UA_NS0ID_BASEOBJECTTYPE, UA_NS0ID_HASSUBTYPE);
addObjectTypeNode(server, "ServerCapatilitiesType", UA_NS0ID_SERVERCAPABILITIESTYPE,
UA_NS0ID_BASEOBJECTTYPE, UA_NS0ID_HASSUBTYPE);
addObjectTypeNode(server, "ServerStatusType", UA_NS0ID_SERVERSTATUSTYPE, UA_NS0ID_BASEOBJECTTYPE,
UA_NS0ID_HASSUBTYPE);
addObjectTypeNode(server, "BuildInfoType", UA_NS0ID_BUILDINFOTYPE, UA_NS0ID_BASEOBJECTTYPE,
UA_NS0ID_HASSUBTYPE);
/**************/
/* Data Types */
/**************/
UA_ObjectNode *datatypes = UA_NodeStore_newObjectNode();
copyNames((UA_Node*)datatypes, "DataTypes");
datatypes->nodeId.identifier.numeric = UA_NS0ID_DATATYPESFOLDER;
addNodeInternal(server, (UA_Node*)datatypes, UA_NODEID_NUMERIC(0, UA_NS0ID_TYPESFOLDER), nodeIdOrganizes);
addReferenceInternal(server, UA_NODEID_NUMERIC(0, UA_NS0ID_DATATYPESFOLDER), nodeIdHasTypeDefinition,
UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_FOLDERTYPE), true);
addDataTypeNode(server, "BaseDataType", UA_NS0ID_BASEDATATYPE, UA_NS0ID_DATATYPESFOLDER);
addDataTypeNode(server, "Boolean", UA_NS0ID_BOOLEAN, UA_NS0ID_BASEDATATYPE);
addDataTypeNode(server, "Number", UA_NS0ID_NUMBER, UA_NS0ID_BASEDATATYPE);
addDataTypeNode(server, "Float", UA_NS0ID_FLOAT, UA_NS0ID_NUMBER);
addDataTypeNode(server, "Double", UA_NS0ID_DOUBLE, UA_NS0ID_NUMBER);
addDataTypeNode(server, "Integer", UA_NS0ID_INTEGER, UA_NS0ID_NUMBER);
addDataTypeNode(server, "SByte", UA_NS0ID_SBYTE, UA_NS0ID_INTEGER);
addDataTypeNode(server, "Int16", UA_NS0ID_INT16, UA_NS0ID_INTEGER);
addDataTypeNode(server, "Int32", UA_NS0ID_INT32, UA_NS0ID_INTEGER);
addDataTypeNode(server, "Int64", UA_NS0ID_INT64, UA_NS0ID_INTEGER);
addDataTypeNode(server, "UInteger", UA_NS0ID_UINTEGER, UA_NS0ID_INTEGER);
addDataTypeNode(server, "Byte", UA_NS0ID_BYTE, UA_NS0ID_UINTEGER);
addDataTypeNode(server, "UInt16", UA_NS0ID_UINT16, UA_NS0ID_UINTEGER);
addDataTypeNode(server, "UInt32", UA_NS0ID_UINT32, UA_NS0ID_UINTEGER);
addDataTypeNode(server, "UInt64", UA_NS0ID_UINT64, UA_NS0ID_UINTEGER);
addDataTypeNode(server, "String", UA_NS0ID_STRING, UA_NS0ID_BASEDATATYPE);
addDataTypeNode(server, "DateTime", UA_NS0ID_DATETIME, UA_NS0ID_BASEDATATYPE);
addDataTypeNode(server, "Guid", UA_NS0ID_GUID, UA_NS0ID_BASEDATATYPE);
addDataTypeNode(server, "ByteString", UA_NS0ID_BYTESTRING, UA_NS0ID_BASEDATATYPE);
addDataTypeNode(server, "XmlElement", UA_NS0ID_XMLELEMENT, UA_NS0ID_BASEDATATYPE);
addDataTypeNode(server, "NodeId", UA_NS0ID_NODEID, UA_NS0ID_BASEDATATYPE);
addDataTypeNode(server, "ExpandedNodeId", UA_NS0ID_EXPANDEDNODEID, UA_NS0ID_BASEDATATYPE);
addDataTypeNode(server, "StatusCode", UA_NS0ID_STATUSCODE, UA_NS0ID_BASEDATATYPE);
addDataTypeNode(server, "QualifiedName", UA_NS0ID_QUALIFIEDNAME, UA_NS0ID_BASEDATATYPE);
addDataTypeNode(server, "LocalizedText", UA_NS0ID_LOCALIZEDTEXT, UA_NS0ID_BASEDATATYPE);
addDataTypeNode(server, "Structure", UA_NS0ID_STRUCTURE, UA_NS0ID_BASEDATATYPE);
addDataTypeNode(server, "ServerStatusDataType", UA_NS0ID_SERVERSTATUSDATATYPE, UA_NS0ID_STRUCTURE);
addDataTypeNode(server, "BuildInfo", UA_NS0ID_BUILDINFO, UA_NS0ID_STRUCTURE);
addDataTypeNode(server, "DataValue", UA_NS0ID_DATAVALUE, UA_NS0ID_BASEDATATYPE);
addDataTypeNode(server, "DiagnosticInfo", UA_NS0ID_DIAGNOSTICINFO, UA_NS0ID_BASEDATATYPE);
addDataTypeNode(server, "Enumeration", UA_NS0ID_ENUMERATION, UA_NS0ID_BASEDATATYPE);
addDataTypeNode(server, "ServerState", UA_NS0ID_SERVERSTATE, UA_NS0ID_ENUMERATION);
UA_ObjectNode *variabletypes = UA_NodeStore_newObjectNode();
copyNames((UA_Node*)variabletypes, "VariableTypes");
variabletypes->nodeId.identifier.numeric = UA_NS0ID_VARIABLETYPESFOLDER;
addNodeInternal(server, (UA_Node*)variabletypes, UA_NODEID_NUMERIC(0, UA_NS0ID_TYPESFOLDER),
nodeIdOrganizes);
addReferenceInternal(server, UA_NODEID_NUMERIC(0, UA_NS0ID_VARIABLETYPESFOLDER),
nodeIdHasTypeDefinition, UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_FOLDERTYPE), true);
addVariableTypeNode_organized(server, "BaseVariableType", UA_NS0ID_BASEVARIABLETYPE,
UA_NS0ID_VARIABLETYPESFOLDER, true);
addVariableTypeNode_subtype(server, "BaseDataVariableType", UA_NS0ID_BASEDATAVARIABLETYPE,
UA_NS0ID_BASEVARIABLETYPE, false);
addVariableTypeNode_subtype(server, "PropertyType", UA_NS0ID_PROPERTYTYPE,
UA_NS0ID_BASEVARIABLETYPE, false);
#endif
#ifdef UA_ENABLE_GENERATE_NAMESPACE0
//load the generated namespace
ua_namespaceinit_generated(server);
#endif
/*********************/
/* The Server Object */
/*********************/
UA_ObjectNode *servernode = UA_NodeStore_newObjectNode();
copyNames((UA_Node*)servernode, "Server");
servernode->nodeId.identifier.numeric = UA_NS0ID_SERVER;
addNodeInternal(server, (UA_Node*)servernode, UA_NODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER),
nodeIdOrganizes);
addReferenceInternal(server, UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER), nodeIdHasTypeDefinition,
UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_SERVERTYPE), true);
UA_VariableNode *namespaceArray = UA_NodeStore_newVariableNode();
copyNames((UA_Node*)namespaceArray, "NamespaceArray");
namespaceArray->nodeId.identifier.numeric = UA_NS0ID_SERVER_NAMESPACEARRAY;
namespaceArray->valueSource = UA_VALUESOURCE_DATASOURCE;
namespaceArray->value.dataSource = (UA_DataSource) {.handle = server, .read = readNamespaces,
.write = NULL};
namespaceArray->valueRank = 1;
namespaceArray->minimumSamplingInterval = 1.0;
addNodeInternal(server, (UA_Node*)namespaceArray, UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER), nodeIdHasProperty);
addReferenceInternal(server, UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_NAMESPACEARRAY),
nodeIdHasTypeDefinition, UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_PROPERTYTYPE), true);
UA_VariableNode *serverArray = UA_NodeStore_newVariableNode();
copyNames((UA_Node*)serverArray, "ServerArray");
serverArray->nodeId.identifier.numeric = UA_NS0ID_SERVER_SERVERARRAY;
UA_Variant_setArrayCopy(&serverArray->value.variant.value,
&server->config.applicationDescription.applicationUri, 1,
&UA_TYPES[UA_TYPES_STRING]);
serverArray->valueRank = 1;
serverArray->minimumSamplingInterval = 1.0;
addNodeInternal(server, (UA_Node*)serverArray, UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER), nodeIdHasProperty);
addReferenceInternal(server, UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERARRAY), nodeIdHasTypeDefinition,
UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_PROPERTYTYPE), true);
UA_ObjectNode *servercapablities = UA_NodeStore_newObjectNode();
copyNames((UA_Node*)servercapablities, "ServerCapabilities");
servercapablities->nodeId.identifier.numeric = UA_NS0ID_SERVER_SERVERCAPABILITIES;
addNodeInternal(server, (UA_Node*)servercapablities, UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER),
nodeIdHasComponent);
addReferenceInternal(server, UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERCAPABILITIES), nodeIdHasTypeDefinition,
UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_SERVERCAPABILITIESTYPE), true);
UA_VariableNode *localeIdArray = UA_NodeStore_newVariableNode();
copyNames((UA_Node*)localeIdArray, "LocaleIdArray");
localeIdArray->nodeId.identifier.numeric = UA_NS0ID_SERVER_SERVERCAPABILITIES_LOCALEIDARRAY;
localeIdArray->value.variant.value.data = UA_Array_new(1, &UA_TYPES[UA_TYPES_STRING]);
localeIdArray->value.variant.value.arrayLength = 1;
localeIdArray->value.variant.value.type = &UA_TYPES[UA_TYPES_STRING];
*(UA_String *)localeIdArray->value.variant.value.data = UA_STRING_ALLOC("en");
localeIdArray->valueRank = 1;
localeIdArray->minimumSamplingInterval = 1.0;
addNodeInternal(server, (UA_Node*)localeIdArray,
UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERCAPABILITIES), nodeIdHasProperty);
addReferenceInternal(server, UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERCAPABILITIES_LOCALEIDARRAY),
nodeIdHasTypeDefinition, UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_PROPERTYTYPE), true);
UA_VariableNode *maxBrowseContinuationPoints = UA_NodeStore_newVariableNode();
copyNames((UA_Node*)maxBrowseContinuationPoints, "MaxBrowseContinuationPoints");
maxBrowseContinuationPoints->nodeId.identifier.numeric =
UA_NS0ID_SERVER_SERVERCAPABILITIES_MAXBROWSECONTINUATIONPOINTS;
maxBrowseContinuationPoints->value.variant.value.data = UA_UInt16_new();
*((UA_UInt16*)maxBrowseContinuationPoints->value.variant.value.data) = MAXCONTINUATIONPOINTS;
maxBrowseContinuationPoints->value.variant.value.type = &UA_TYPES[UA_TYPES_UINT16];
addNodeInternal(server, (UA_Node*)maxBrowseContinuationPoints,
UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERCAPABILITIES), nodeIdHasProperty);
addReferenceInternal(server, UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERCAPABILITIES_MAXBROWSECONTINUATIONPOINTS),
nodeIdHasTypeDefinition, UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_PROPERTYTYPE), true);
/** ServerProfileArray **/
#define MAX_PROFILEARRAY 16 //a *magic* limit to the number of supported profiles
#define ADDPROFILEARRAY(x) profileArray[profileArraySize++] = UA_STRING_ALLOC(x)
UA_String profileArray[MAX_PROFILEARRAY];
UA_UInt16 profileArraySize = 0;
ADDPROFILEARRAY("http://opcfoundation.org/UA-Profile/Server/NanoEmbeddedDevice");
#ifdef UA_ENABLE_SERVICESET_NODEMANAGEMENT
ADDPROFILEARRAY("http://opcfoundation.org/UA-Profile/Server/NodeManagement");
#endif
#ifdef UA_ENABLE_SERVICESET_METHOD
ADDPROFILEARRAY("http://opcfoundation.org/UA-Profile/Server/Methods");
#endif
#ifdef UA_ENABLE_SUBSCRIPTIONS
ADDPROFILEARRAY("http://opcfoundation.org/UA-Profile/Server/EmbeddedDataChangeSubscription");
#endif
UA_VariableNode *serverProfileArray = UA_NodeStore_newVariableNode();
copyNames((UA_Node*)serverProfileArray, "ServerProfileArray");
serverProfileArray->nodeId.identifier.numeric = UA_NS0ID_SERVER_SERVERCAPABILITIES_SERVERPROFILEARRAY;
serverProfileArray->value.variant.value.arrayLength = profileArraySize;
serverProfileArray->value.variant.value.data = UA_Array_new(profileArraySize, &UA_TYPES[UA_TYPES_STRING]);
serverProfileArray->value.variant.value.type = &UA_TYPES[UA_TYPES_STRING];
for(UA_UInt16 i=0;i<profileArraySize;i++)
((UA_String *)serverProfileArray->value.variant.value.data)[i] = profileArray[i];
serverProfileArray->valueRank = 1;
serverProfileArray->minimumSamplingInterval = 1.0;
addNodeInternal(server, (UA_Node*)serverProfileArray,
UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERCAPABILITIES), nodeIdHasProperty);
addReferenceInternal(server, UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERCAPABILITIES_SERVERPROFILEARRAY),
nodeIdHasTypeDefinition, UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_PROPERTYTYPE), true);
UA_ObjectNode *serverdiagnostics = UA_NodeStore_newObjectNode();
copyNames((UA_Node*)serverdiagnostics, "ServerDiagnostics");
serverdiagnostics->nodeId.identifier.numeric = UA_NS0ID_SERVER_SERVERDIAGNOSTICS;
addNodeInternal(server, (UA_Node*)serverdiagnostics,
UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER), nodeIdHasComponent);
addReferenceInternal(server, UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERDIAGNOSTICS),
nodeIdHasTypeDefinition, UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_SERVERDIAGNOSTICSTYPE), true);
UA_VariableNode *enabledFlag = UA_NodeStore_newVariableNode();
copyNames((UA_Node*)enabledFlag, "EnabledFlag");
enabledFlag->nodeId.identifier.numeric = UA_NS0ID_SERVER_SERVERDIAGNOSTICS_ENABLEDFLAG;
enabledFlag->value.variant.value.data = UA_Boolean_new(); //initialized as false
enabledFlag->value.variant.value.type = &UA_TYPES[UA_TYPES_BOOLEAN];
enabledFlag->valueRank = 1;
enabledFlag->minimumSamplingInterval = 1.0;
addNodeInternal(server, (UA_Node*)enabledFlag,
UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERDIAGNOSTICS), nodeIdHasProperty);
addReferenceInternal(server, UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERDIAGNOSTICS_ENABLEDFLAG),
nodeIdHasTypeDefinition, UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_PROPERTYTYPE), true);
UA_VariableNode *serverstatus = UA_NodeStore_newVariableNode();
copyNames((UA_Node*)serverstatus, "ServerStatus");
serverstatus->nodeId = UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERSTATUS);
serverstatus->valueSource = UA_VALUESOURCE_DATASOURCE;
serverstatus->value.dataSource = (UA_DataSource) {.handle = server, .read = readStatus, .write = NULL};
addNodeInternal(server, (UA_Node*)serverstatus, UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER), nodeIdHasComponent);
addReferenceInternal(server, UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERSTATUS), nodeIdHasTypeDefinition,
UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_SERVERSTATUSTYPE), true);
UA_VariableNode *starttime = UA_NodeStore_newVariableNode();
copyNames((UA_Node*)starttime, "StartTime");
starttime->nodeId = UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERSTATUS_STARTTIME);
starttime->value.variant.value.storageType = UA_VARIANT_DATA_NODELETE;
starttime->value.variant.value.data = &server->startTime;
starttime->value.variant.value.type = &UA_TYPES[UA_TYPES_DATETIME];
addNodeInternal(server, (UA_Node*)starttime, UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERSTATUS),
nodeIdHasComponent);
addReferenceInternal(server, UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERSTATUS_STARTTIME),
nodeIdHasTypeDefinition, expandedNodeIdBaseDataVariabletype, true);
UA_VariableNode *currenttime = UA_NodeStore_newVariableNode();
copyNames((UA_Node*)currenttime, "CurrentTime");
currenttime->nodeId = UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERSTATUS_CURRENTTIME);
currenttime->valueSource = UA_VALUESOURCE_DATASOURCE;
currenttime->value.dataSource = (UA_DataSource) {.handle = NULL, .read = readCurrentTime,
.write = NULL};
addNodeInternal(server, (UA_Node*)currenttime,
UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERSTATUS), nodeIdHasComponent);
addReferenceInternal(server, UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERSTATUS_CURRENTTIME),
nodeIdHasTypeDefinition, expandedNodeIdBaseDataVariabletype, true);
UA_VariableNode *state = UA_NodeStore_newVariableNode();
UA_ServerState *stateEnum = UA_ServerState_new();
*stateEnum = UA_SERVERSTATE_RUNNING;
copyNames((UA_Node*)state, "State");
state->nodeId.identifier.numeric = UA_NS0ID_SERVER_SERVERSTATUS_STATE;
state->value.variant.value.type = &UA_TYPES[UA_TYPES_SERVERSTATE];
state->value.variant.value.arrayLength = 0;
state->value.variant.value.data = stateEnum; // points into the other object.
addNodeInternal(server, (UA_Node*)state, UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERSTATUS),
nodeIdHasComponent);
addReferenceInternal(server, UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERSTATUS_STATE),
nodeIdHasTypeDefinition, expandedNodeIdBaseDataVariabletype, true);
UA_VariableNode *buildinfo = UA_NodeStore_newVariableNode();
copyNames((UA_Node*)buildinfo, "BuildInfo");
buildinfo->nodeId = UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERSTATUS_BUILDINFO);
UA_Variant_setScalarCopy(&buildinfo->value.variant.value,
&server->config.buildInfo,
&UA_TYPES[UA_TYPES_BUILDINFO]);
addNodeInternal(server, (UA_Node*)buildinfo,
UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERSTATUS), nodeIdHasComponent);
addReferenceInternal(server, UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERSTATUS_BUILDINFO),
nodeIdHasTypeDefinition, UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_BUILDINFOTYPE), true);
UA_VariableNode *producturi = UA_NodeStore_newVariableNode();
copyNames((UA_Node*)producturi, "ProductUri");
producturi->nodeId = UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERSTATUS_BUILDINFO_PRODUCTURI);
UA_Variant_setScalarCopy(&producturi->value.variant.value, &server->config.buildInfo.productUri,
&UA_TYPES[UA_TYPES_STRING]);
producturi->value.variant.value.type = &UA_TYPES[UA_TYPES_STRING];
addNodeInternal(server, (UA_Node*)producturi,
UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERSTATUS_BUILDINFO), nodeIdHasComponent);
addReferenceInternal(server, UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERSTATUS_BUILDINFO_PRODUCTURI),
nodeIdHasTypeDefinition, expandedNodeIdBaseDataVariabletype, true);
UA_VariableNode *manufacturername = UA_NodeStore_newVariableNode();
copyNames((UA_Node*)manufacturername, "ManufacturerName");
manufacturername->nodeId = UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERSTATUS_BUILDINFO_MANUFACTURERNAME);
UA_Variant_setScalarCopy(&manufacturername->value.variant.value,
&server->config.buildInfo.manufacturerName,
&UA_TYPES[UA_TYPES_STRING]);
addNodeInternal(server, (UA_Node*)manufacturername,
UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERSTATUS_BUILDINFO), nodeIdHasComponent);
addReferenceInternal(server, UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERSTATUS_BUILDINFO_MANUFACTURERNAME),
nodeIdHasTypeDefinition, expandedNodeIdBaseDataVariabletype, true);
UA_VariableNode *productname = UA_NodeStore_newVariableNode();
copyNames((UA_Node*)productname, "ProductName");
productname->nodeId = UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERSTATUS_BUILDINFO_PRODUCTNAME);
UA_Variant_setScalarCopy(&productname->value.variant.value, &server->config.buildInfo.productName,
&UA_TYPES[UA_TYPES_STRING]);
addNodeInternal(server, (UA_Node*)productname,
UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERSTATUS_BUILDINFO), nodeIdHasComponent);
addReferenceInternal(server, UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERSTATUS_BUILDINFO_PRODUCTNAME),
nodeIdHasTypeDefinition, expandedNodeIdBaseDataVariabletype, true);
UA_VariableNode *softwareversion = UA_NodeStore_newVariableNode();
copyNames((UA_Node*)softwareversion, "SoftwareVersion");
softwareversion->nodeId = UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERSTATUS_BUILDINFO_SOFTWAREVERSION);
UA_Variant_setScalarCopy(&softwareversion->value.variant.value, &server->config.buildInfo.softwareVersion,
&UA_TYPES[UA_TYPES_STRING]);
addNodeInternal(server, (UA_Node*)softwareversion,
UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERSTATUS_BUILDINFO), nodeIdHasComponent);
addReferenceInternal(server, UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERSTATUS_BUILDINFO_SOFTWAREVERSION),
nodeIdHasTypeDefinition, expandedNodeIdBaseDataVariabletype, true);
UA_VariableNode *buildnumber = UA_NodeStore_newVariableNode();
copyNames((UA_Node*)buildnumber, "BuildNumber");
buildnumber->nodeId = UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERSTATUS_BUILDINFO_BUILDNUMBER);
UA_Variant_setScalarCopy(&buildnumber->value.variant.value, &server->config.buildInfo.buildNumber,
&UA_TYPES[UA_TYPES_STRING]);
addNodeInternal(server, (UA_Node*)buildnumber,
UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERSTATUS_BUILDINFO), nodeIdHasComponent);
addReferenceInternal(server, UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERSTATUS_BUILDINFO_BUILDNUMBER),
nodeIdHasTypeDefinition, expandedNodeIdBaseDataVariabletype, true);
UA_VariableNode *builddate = UA_NodeStore_newVariableNode();
copyNames((UA_Node*)builddate, "BuildDate");
builddate->nodeId = UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERSTATUS_BUILDINFO_BUILDDATE);
UA_Variant_setScalarCopy(&builddate->value.variant.value, &server->config.buildInfo.buildDate,
&UA_TYPES[UA_TYPES_DATETIME]);
addNodeInternal(server, (UA_Node*)builddate,
UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERSTATUS_BUILDINFO), nodeIdHasComponent);
addReferenceInternal(server, UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERSTATUS_BUILDINFO_BUILDNUMBER),
nodeIdHasTypeDefinition, expandedNodeIdBaseDataVariabletype, true);
UA_VariableNode *secondstillshutdown = UA_NodeStore_newVariableNode();
copyNames((UA_Node*)secondstillshutdown, "SecondsTillShutdown");
secondstillshutdown->nodeId = UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERSTATUS_SECONDSTILLSHUTDOWN);
secondstillshutdown->value.variant.value.data = UA_UInt32_new();
secondstillshutdown->value.variant.value.type = &UA_TYPES[UA_TYPES_UINT32];
addNodeInternal(server, (UA_Node*)secondstillshutdown,
UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERSTATUS), nodeIdHasComponent);
addReferenceInternal(server, UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERSTATUS_SECONDSTILLSHUTDOWN),
nodeIdHasTypeDefinition, expandedNodeIdBaseDataVariabletype, true);
UA_VariableNode *shutdownreason = UA_NodeStore_newVariableNode();
copyNames((UA_Node*)shutdownreason, "ShutdownReason");
shutdownreason->nodeId = UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERSTATUS_SHUTDOWNREASON);
shutdownreason->value.variant.value.data = UA_LocalizedText_new();
shutdownreason->value.variant.value.type = &UA_TYPES[UA_TYPES_LOCALIZEDTEXT];
addNodeInternal(server, (UA_Node*)shutdownreason,
UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERSTATUS), nodeIdHasComponent);
addReferenceInternal(server, UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERSTATUS_SHUTDOWNREASON),
nodeIdHasTypeDefinition, expandedNodeIdBaseDataVariabletype, true);
return server;
}
UA_StatusCode
__UA_Server_write(UA_Server *server, const UA_NodeId *nodeId,
const UA_AttributeId attributeId, const UA_DataType *attr_type,
const void *value) {
UA_WriteValue wvalue;
UA_WriteValue_init(&wvalue);
wvalue.nodeId = *nodeId;
wvalue.attributeId = attributeId;
if(attributeId != UA_ATTRIBUTEID_VALUE)
/* hacked cast. the target WriteValue is used as const anyway */
UA_Variant_setScalar(&wvalue.value.value, (void*)(uintptr_t)value, attr_type);
else {
if(attr_type != &UA_TYPES[UA_TYPES_VARIANT])
return UA_STATUSCODE_BADTYPEMISMATCH;
wvalue.value.value = *(const UA_Variant*)value;
}
wvalue.value.hasValue = true;
UA_RCU_LOCK();
UA_StatusCode retval = Service_Write_single(server, &adminSession, &wvalue);
UA_RCU_UNLOCK();
return retval;
}
static UA_StatusCode
setValueCallback(UA_Server *server, UA_Session *session, UA_VariableNode *node, UA_ValueCallback *callback) {
if(node->nodeClass != UA_NODECLASS_VARIABLE)
return UA_STATUSCODE_BADNODECLASSINVALID;
node->value.variant.callback = *callback;
return UA_STATUSCODE_GOOD;
}
UA_StatusCode UA_EXPORT
UA_Server_setVariableNode_valueCallback(UA_Server *server, const UA_NodeId nodeId,
const UA_ValueCallback callback) {
UA_RCU_LOCK();
UA_StatusCode retval = UA_Server_editNode(server, &adminSession, &nodeId,
(UA_EditNodeCallback)setValueCallback, &callback);
UA_RCU_UNLOCK();
return retval;
}
static UA_StatusCode
setDataSource(UA_Server *server, UA_Session *session,
UA_VariableNode* node, UA_DataSource *dataSource) {
if(node->nodeClass != UA_NODECLASS_VARIABLE)
return UA_STATUSCODE_BADNODECLASSINVALID;
if(node->valueSource == UA_VALUESOURCE_VARIANT)
UA_Variant_deleteMembers(&node->value.variant.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) {
UA_RCU_LOCK();
UA_StatusCode retval = UA_Server_editNode(server, &adminSession, &nodeId,
(UA_EditNodeCallback)setDataSource, &dataSource);
UA_RCU_UNLOCK();
return retval;
}
static UA_StatusCode
setObjectTypeLifecycleManagement(UA_Server *server, UA_Session *session, UA_ObjectTypeNode* node,
UA_ObjectLifecycleManagement *olm) {
if(node->nodeClass != UA_NODECLASS_OBJECTTYPE)
return UA_STATUSCODE_BADNODECLASSINVALID;
node->lifecycleManagement = *olm;
return UA_STATUSCODE_GOOD;
}
UA_StatusCode UA_EXPORT
UA_Server_setObjectTypeNode_lifecycleManagement(UA_Server *server, UA_NodeId nodeId,
UA_ObjectLifecycleManagement olm) {
UA_RCU_LOCK();
UA_StatusCode retval = UA_Server_editNode(server, &adminSession, &nodeId,
(UA_EditNodeCallback)setObjectTypeLifecycleManagement, &olm);
UA_RCU_UNLOCK();
return retval;
}
#ifdef UA_ENABLE_METHODCALLS
struct addMethodCallback {
UA_MethodCallback callback;
void *handle;
};
static UA_StatusCode
editMethodCallback(UA_Server *server, UA_Session* session, UA_Node* node, const void* handle) {
if(node->nodeClass != UA_NODECLASS_METHOD)
return UA_STATUSCODE_BADNODECLASSINVALID;
const struct addMethodCallback *newCallback = handle;
UA_MethodNode *mnode = (UA_MethodNode*) node;
mnode->attachedMethod = newCallback->callback;
mnode->methodHandle = newCallback->handle;
return UA_STATUSCODE_GOOD;
}
UA_StatusCode UA_EXPORT
UA_Server_setMethodNode_callback(UA_Server *server, const UA_NodeId methodNodeId,
UA_MethodCallback method, void *handle) {
struct addMethodCallback cb = { method, handle };
UA_RCU_LOCK();
UA_StatusCode retval = UA_Server_editNode(server, &adminSession, &methodNodeId, editMethodCallback, &cb);
UA_RCU_UNLOCK();
return retval;
}
#endif
UA_StatusCode
__UA_Server_read(UA_Server *server, const UA_NodeId *nodeId, const UA_AttributeId attributeId, void *v) {
UA_ReadValueId item;
UA_ReadValueId_init(&item);
item.nodeId = *nodeId;
item.attributeId = attributeId;
UA_DataValue dv;
UA_DataValue_init(&dv);
UA_RCU_LOCK();
Service_Read_single(server, &adminSession, UA_TIMESTAMPSTORETURN_NEITHER,
&item, &dv);
UA_RCU_UNLOCK();
UA_StatusCode retval = UA_STATUSCODE_GOOD;
if(dv.hasStatus)
retval = dv.hasStatus;
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)
memcpy(v, &dv.value, sizeof(UA_Variant));
else {
memcpy(v, dv.value.data, dv.value.type->memSize);
dv.value.data = NULL;
dv.value.arrayLength = 0;
UA_Variant_deleteMembers(&dv.value);
}
return UA_STATUSCODE_GOOD;
}
UA_BrowseResult
UA_Server_browse(UA_Server *server, UA_UInt32 maxrefs, const UA_BrowseDescription *descr) {
UA_BrowseResult result;
UA_BrowseResult_init(&result);
UA_RCU_LOCK();
Service_Browse_single(server, &adminSession, NULL, descr, maxrefs, &result);
UA_RCU_UNLOCK();
return result;
}
UA_BrowseResult
UA_Server_browseNext(UA_Server *server, UA_Boolean releaseContinuationPoint,
const UA_ByteString *continuationPoint) {
UA_BrowseResult result;
UA_BrowseResult_init(&result);
UA_RCU_LOCK();
UA_Server_browseNext_single(server, &adminSession, releaseContinuationPoint,
continuationPoint, &result);
UA_RCU_UNLOCK();
return result;
}
#ifdef UA_ENABLE_METHODCALLS
UA_CallMethodResult UA_Server_call(UA_Server *server, const UA_CallMethodRequest *request) {
UA_CallMethodResult result;
UA_CallMethodResult_init(&result);
UA_RCU_LOCK();
Service_Call_single(server, &adminSession, request, &result);
UA_RCU_UNLOCK();
return result;
}
#endif
/*********************************** amalgamated original file "/home/wn/Sources/open62541-open62541-395ce48/src/server/ua_server_binary.c" ***********************************/
/** Max size of messages that are allocated on the stack */
#define MAX_STACK_MESSAGE 65536
static void processHEL(UA_Connection *connection, const UA_ByteString *msg, size_t *pos) {
UA_TcpHelloMessage helloMessage;
if(UA_TcpHelloMessage_decodeBinary(msg, pos, &helloMessage) != UA_STATUSCODE_GOOD) {
connection->close(connection);
return;
}
connection->remoteConf.maxChunkCount = helloMessage.maxChunkCount;
connection->remoteConf.maxMessageSize = helloMessage.maxMessageSize;
connection->remoteConf.protocolVersion = helloMessage.protocolVersion;
connection->remoteConf.recvBufferSize = helloMessage.receiveBufferSize;
if(connection->localConf.sendBufferSize > helloMessage.receiveBufferSize)
connection->localConf.sendBufferSize = helloMessage.receiveBufferSize;
if(connection->localConf.recvBufferSize > helloMessage.sendBufferSize)
connection->localConf.recvBufferSize = helloMessage.sendBufferSize;
connection->remoteConf.sendBufferSize = helloMessage.sendBufferSize;
connection->state = UA_CONNECTION_ESTABLISHED;
UA_TcpHelloMessage_deleteMembers(&helloMessage);
// 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 */
UA_ByteString ack_msg;
UA_ByteString_init(&ack_msg);
if(connection->getSendBuffer(connection, connection->localConf.sendBufferSize,
&ack_msg) != UA_STATUSCODE_GOOD)
return;
size_t tmpPos = 0;
UA_TcpMessageHeader_encodeBinary(&ackHeader, &ack_msg, &tmpPos);
UA_TcpAcknowledgeMessage_encodeBinary(&ackMessage, &ack_msg, &tmpPos);
ack_msg.length = ackHeader.messageSize;
connection->send(connection, &ack_msg);
}
static void processOPN(UA_Connection *connection, UA_Server *server, const UA_ByteString *msg, size_t *pos) {
if(connection->state != UA_CONNECTION_ESTABLISHED) {
connection->close(connection);
return;
}
UA_UInt32 secureChannelId;
UA_StatusCode retval = UA_UInt32_decodeBinary(msg, pos, &secureChannelId);
//we can check secureChannelId also here -> if we are asked to isse a token it is 0, otherwise we have to renew
//issue
if(connection->channel == NULL && secureChannelId != 0){
retval |= UA_STATUSCODE_BADREQUESTTYPEINVALID;
}
//renew
if(connection->channel != NULL && secureChannelId != connection->channel->securityToken.channelId){
retval |= UA_STATUSCODE_BADREQUESTTYPEINVALID;
}
UA_AsymmetricAlgorithmSecurityHeader asymHeader;
retval |= UA_AsymmetricAlgorithmSecurityHeader_decodeBinary(msg, pos, &asymHeader);
UA_SequenceHeader seqHeader;
retval |= UA_SequenceHeader_decodeBinary(msg, pos, &seqHeader);
UA_NodeId requestType;
retval |= UA_NodeId_decodeBinary(msg, pos, &requestType);
UA_OpenSecureChannelRequest r;
retval |= UA_OpenSecureChannelRequest_decodeBinary(msg, pos, &r);
if(retval != UA_STATUSCODE_GOOD || requestType.identifier.numeric != 446) {
UA_AsymmetricAlgorithmSecurityHeader_deleteMembers(&asymHeader);
UA_SequenceHeader_deleteMembers(&seqHeader);
UA_NodeId_deleteMembers(&requestType);
UA_OpenSecureChannelRequest_deleteMembers(&r);
connection->close(connection);
return;
}
UA_OpenSecureChannelResponse p;
UA_OpenSecureChannelResponse_init(&p);
Service_OpenSecureChannel(server, connection, &r, &p);
UA_OpenSecureChannelRequest_deleteMembers(&r);
UA_SecureChannel *channel = connection->channel;
if(!channel) {
connection->close(connection);
UA_OpenSecureChannelResponse_deleteMembers(&p);
UA_AsymmetricAlgorithmSecurityHeader_deleteMembers(&asymHeader);
return;
}
/* send the response with an asymmetric security header */
#ifndef UA_ENABLE_MULTITHREADING
seqHeader.sequenceNumber = ++channel->sequenceNumber;
#else
seqHeader.sequenceNumber = uatomic_add_return(&channel->sequenceNumber, 1);
#endif
UA_SecureConversationMessageHeader respHeader;
respHeader.messageHeader.messageTypeAndChunkType = UA_MESSAGETYPE_OPN + UA_CHUNKTYPE_FINAL;
respHeader.messageHeader.messageSize = 0;
respHeader.secureChannelId = p.securityToken.channelId;
UA_NodeId responseType = UA_NODEID_NUMERIC(0, UA_NS0ID_OPENSECURECHANNELRESPONSE +
UA_ENCODINGOFFSET_BINARY);
UA_ByteString resp_msg;
UA_ByteString_init(&resp_msg);
retval = connection->getSendBuffer(connection, connection->localConf.sendBufferSize, &resp_msg);
if(retval != UA_STATUSCODE_GOOD) {
UA_OpenSecureChannelResponse_deleteMembers(&p);
UA_AsymmetricAlgorithmSecurityHeader_deleteMembers(&asymHeader);
return;
}
size_t tmpPos = 12; /* skip the secureconversationmessageheader for now */
retval |= UA_AsymmetricAlgorithmSecurityHeader_encodeBinary(&asymHeader, &resp_msg, &tmpPos); // just mirror back
retval |= UA_SequenceHeader_encodeBinary(&seqHeader, &resp_msg, &tmpPos); // just mirror back
retval |= UA_NodeId_encodeBinary(&responseType, &resp_msg, &tmpPos);
retval |= UA_OpenSecureChannelResponse_encodeBinary(&p, &resp_msg, &tmpPos);
if(retval != UA_STATUSCODE_GOOD) {
connection->releaseSendBuffer(connection, &resp_msg);
connection->close(connection);
} else {
respHeader.messageHeader.messageSize = (UA_UInt32)tmpPos;
tmpPos = 0;
UA_SecureConversationMessageHeader_encodeBinary(&respHeader, &resp_msg, &tmpPos);
resp_msg.length = respHeader.messageHeader.messageSize;
connection->send(connection, &resp_msg);
}
UA_OpenSecureChannelResponse_deleteMembers(&p);
UA_AsymmetricAlgorithmSecurityHeader_deleteMembers(&asymHeader);
}
static void init_response_header(const UA_RequestHeader *p, UA_ResponseHeader *r) {
r->requestHandle = p->requestHandle;
r->timestamp = UA_DateTime_now();
}
static void
getServicePointers(UA_UInt32 requestTypeId, const UA_DataType **requestType,
const UA_DataType **responseType, UA_Service *service) {
switch(requestTypeId - UA_ENCODINGOFFSET_BINARY) {
case UA_NS0ID_GETENDPOINTSREQUEST:
*service = (UA_Service)Service_GetEndpoints;
*requestType = &UA_TYPES[UA_TYPES_GETENDPOINTSREQUEST];
*responseType = &UA_TYPES[UA_TYPES_GETENDPOINTSRESPONSE];
break;
case UA_NS0ID_FINDSERVERSREQUEST:
*service = (UA_Service)Service_FindServers;
*requestType = &UA_TYPES[UA_TYPES_FINDSERVERSREQUEST];
*responseType = &UA_TYPES[UA_TYPES_FINDSERVERSRESPONSE];
break;
case UA_NS0ID_CREATESESSIONREQUEST:
*service = (UA_Service)Service_CreateSession;
*requestType = &UA_TYPES[UA_TYPES_CREATESESSIONREQUEST];
*responseType = &UA_TYPES[UA_TYPES_CREATESESSIONRESPONSE];
break;
case UA_NS0ID_ACTIVATESESSIONREQUEST:
*service = (UA_Service)Service_ActivateSession;
*requestType = &UA_TYPES[UA_TYPES_ACTIVATESESSIONREQUEST];
*responseType = &UA_TYPES[UA_TYPES_ACTIVATESESSIONRESPONSE];
break;
case UA_NS0ID_CLOSESESSIONREQUEST:
*service = (UA_Service)Service_CloseSession;
*requestType = &UA_TYPES[UA_TYPES_CLOSESESSIONREQUEST];
*responseType = &UA_TYPES[UA_TYPES_CLOSESESSIONRESPONSE];
break;
case UA_NS0ID_READREQUEST:
*service = (UA_Service)Service_Read;
*requestType = &UA_TYPES[UA_TYPES_READREQUEST];
*responseType = &UA_TYPES[UA_TYPES_READRESPONSE];
break;
case UA_NS0ID_WRITEREQUEST:
*service = (UA_Service)Service_Write;
*requestType = &UA_TYPES[UA_TYPES_WRITEREQUEST];
*responseType = &UA_TYPES[UA_TYPES_WRITERESPONSE];
break;
case UA_NS0ID_BROWSEREQUEST:
*service = (UA_Service)Service_Browse;
*requestType = &UA_TYPES[UA_TYPES_BROWSEREQUEST];
*responseType = &UA_TYPES[UA_TYPES_BROWSERESPONSE];
break;
case UA_NS0ID_BROWSENEXTREQUEST:
*service = (UA_Service)Service_BrowseNext;
*requestType = &UA_TYPES[UA_TYPES_BROWSENEXTREQUEST];
*responseType = &UA_TYPES[UA_TYPES_BROWSENEXTRESPONSE];
break;
case UA_NS0ID_REGISTERNODESREQUEST:
*service = (UA_Service)Service_RegisterNodes;
*requestType = &UA_TYPES[UA_TYPES_REGISTERNODESREQUEST];
*responseType = &UA_TYPES[UA_TYPES_REGISTERNODESRESPONSE];
break;
case UA_NS0ID_UNREGISTERNODESREQUEST:
*service = (UA_Service)Service_UnregisterNodes;
*requestType = &UA_TYPES[UA_TYPES_UNREGISTERNODESREQUEST];
*responseType = &UA_TYPES[UA_TYPES_UNREGISTERNODESRESPONSE];
break;
case UA_NS0ID_TRANSLATEBROWSEPATHSTONODEIDSREQUEST:
*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:
*service = (UA_Service)Service_CreateSubscription;
*requestType = &UA_TYPES[UA_TYPES_CREATESUBSCRIPTIONREQUEST];
*responseType = &UA_TYPES[UA_TYPES_CREATESUBSCRIPTIONRESPONSE];
break;
case UA_NS0ID_PUBLISHREQUEST:
*requestType = &UA_TYPES[UA_TYPES_PUBLISHREQUEST];
*responseType = &UA_TYPES[UA_TYPES_PUBLISHRESPONSE];
break;
case UA_NS0ID_REPUBLISHREQUEST:
*service = (UA_Service)Service_Republish;
*requestType = &UA_TYPES[UA_TYPES_REPUBLISHREQUEST];
*responseType = &UA_TYPES[UA_TYPES_REPUBLISHRESPONSE];
break;
case UA_NS0ID_MODIFYSUBSCRIPTIONREQUEST:
*service = (UA_Service)Service_ModifySubscription;
*requestType = &UA_TYPES[UA_TYPES_MODIFYSUBSCRIPTIONREQUEST];
*responseType = &UA_TYPES[UA_TYPES_MODIFYSUBSCRIPTIONRESPONSE];
break;
case UA_NS0ID_SETPUBLISHINGMODEREQUEST:
*service = (UA_Service)Service_SetPublishingMode;
*requestType = &UA_TYPES[UA_TYPES_SETPUBLISHINGMODEREQUEST];
*responseType = &UA_TYPES[UA_TYPES_SETPUBLISHINGMODERESPONSE];
break;
case UA_NS0ID_DELETESUBSCRIPTIONSREQUEST:
*service = (UA_Service)Service_DeleteSubscriptions;
*requestType = &UA_TYPES[UA_TYPES_DELETESUBSCRIPTIONSREQUEST];
*responseType = &UA_TYPES[UA_TYPES_DELETESUBSCRIPTIONSRESPONSE];
break;
case UA_NS0ID_CREATEMONITOREDITEMSREQUEST:
*service = (UA_Service)Service_CreateMonitoredItems;
*requestType = &UA_TYPES[UA_TYPES_CREATEMONITOREDITEMSREQUEST];
*responseType = &UA_TYPES[UA_TYPES_CREATEMONITOREDITEMSRESPONSE];
break;
case UA_NS0ID_DELETEMONITOREDITEMSREQUEST:
*service = (UA_Service)Service_DeleteMonitoredItems;
*requestType = &UA_TYPES[UA_TYPES_DELETEMONITOREDITEMSREQUEST];
*responseType = &UA_TYPES[UA_TYPES_DELETEMONITOREDITEMSRESPONSE];
break;
case UA_NS0ID_MODIFYMONITOREDITEMSREQUEST:
*service = (UA_Service)Service_ModifyMonitoredItems;
*requestType = &UA_TYPES[UA_TYPES_MODIFYMONITOREDITEMSREQUEST];
*responseType = &UA_TYPES[UA_TYPES_MODIFYMONITOREDITEMSRESPONSE];
break;
#endif
#ifdef UA_ENABLE_METHODCALLS
case UA_NS0ID_CALLREQUEST:
*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:
*service = (UA_Service)Service_AddNodes;
*requestType = &UA_TYPES[UA_TYPES_ADDNODESREQUEST];
*responseType = &UA_TYPES[UA_TYPES_ADDNODESRESPONSE];
break;
case UA_NS0ID_ADDREFERENCESREQUEST:
*service = (UA_Service)Service_AddReferences;
*requestType = &UA_TYPES[UA_TYPES_ADDREFERENCESREQUEST];
*responseType = &UA_TYPES[UA_TYPES_ADDREFERENCESRESPONSE];
break;
case UA_NS0ID_DELETENODESREQUEST:
*service = (UA_Service)Service_DeleteNodes;
*requestType = &UA_TYPES[UA_TYPES_DELETENODESREQUEST];
*responseType = &UA_TYPES[UA_TYPES_DELETENODESRESPONSE];
break;
case UA_NS0ID_DELETEREFERENCESREQUEST:
*service = (UA_Service)Service_DeleteReferences;
*requestType = &UA_TYPES[UA_TYPES_DELETEREFERENCESREQUEST];
*responseType = &UA_TYPES[UA_TYPES_DELETEREFERENCESRESPONSE];
break;
#endif
default:
break;
}
}
static void
sendError(UA_SecureChannel *channel, const UA_ByteString *msg, size_t pos,
UA_UInt32 requestId, UA_StatusCode error) {
UA_RequestHeader p;
if(UA_RequestHeader_decodeBinary(msg, &pos, &p) != UA_STATUSCODE_GOOD)
return;
UA_ResponseHeader r;
UA_ResponseHeader_init(&r);
init_response_header(&p, &r);
r.serviceResult = error;
UA_SecureChannel_sendBinaryMessage(channel, requestId, &r,
&UA_TYPES[UA_TYPES_SERVICEFAULT]);
UA_RequestHeader_deleteMembers(&p);
UA_ResponseHeader_deleteMembers(&r);
}
static void
appendChunkedMessage(struct ChunkEntry *ch, const UA_ByteString *msg, size_t *pos) {
if (ch->invalid_message) {
return;
}
UA_UInt32 len;
*pos -= 20;
UA_UInt32_decodeBinary(msg, pos, &len);
if (len > msg->length) {
UA_ByteString_deleteMembers(&ch->bytes);
ch->invalid_message = true;
return;
}
len -= 24;
*pos += 16; // 4 bytes consumed by decode above
UA_Byte* new_bytes = UA_realloc(ch->bytes.data, ch->bytes.length + len);
if (! new_bytes) {
UA_ByteString_deleteMembers(&ch->bytes);
ch->invalid_message = true;
return;
}
ch->bytes.data = new_bytes;
memcpy(&ch->bytes.data[ch->bytes.length], &msg->data[*pos], len);
ch->bytes.length += len;
*pos += len;
}
static struct ChunkEntry*
chunkEntryFromRequestId(UA_SecureChannel *channel, UA_UInt32 requestId) {
struct ChunkEntry *ch;
LIST_FOREACH(ch, &channel->chunks, pointers) {
if (ch->requestId == requestId) {
return ch;
}
}
return NULL;
}
static void
processMSG(UA_Connection *connection, UA_Server *server, const UA_ByteString *msg, size_t *pos) {
/* If we cannot decode these, don't respond */
UA_UInt32 secureChannelId = 0;
UA_UInt32 tokenId = 0;
UA_SequenceHeader sequenceHeader;
UA_NodeId requestTypeId;
UA_StatusCode retval = UA_UInt32_decodeBinary(msg, pos, &secureChannelId);
retval |= UA_UInt32_decodeBinary(msg, pos, &tokenId);
retval |= UA_SequenceHeader_decodeBinary(msg, pos, &sequenceHeader);
if(retval != UA_STATUSCODE_GOOD)
return;
UA_SecureChannel *channel = connection->channel;
UA_SecureChannel anonymousChannel;
if(!channel) {
UA_SecureChannel_init(&anonymousChannel);
anonymousChannel.connection = connection;
channel = &anonymousChannel;
}
/* Test if the secure channel is ok */
if(secureChannelId != channel->securityToken.channelId)
return;
if(tokenId != channel->securityToken.tokenId) {
if(tokenId != channel->nextSecurityToken.tokenId) {
/* close the securechannel but keep the connection open */
UA_LOG_INFO(server->config.logger, UA_LOGCATEGORY_SECURECHANNEL,
"Request with a wrong security token. Closing the SecureChannel %i.",
channel->securityToken.channelId);
Service_CloseSecureChannel(server, channel->securityToken.channelId);
return;
}
UA_SecureChannel_revolveTokens(channel);
}
size_t final_chunked_pos = 0;
UA_ByteString bytes;
struct ChunkEntry *ch;
switch (msg->data[*pos - 24 + 3]) {
case 'C':
UA_LOG_TRACE(server->config.logger, UA_LOGCATEGORY_SECURECHANNEL, "Chunk message");
ch = chunkEntryFromRequestId(channel, sequenceHeader.requestId);
if (! ch) {
ch = UA_calloc(1, sizeof(struct ChunkEntry));
ch->invalid_message = false;
ch->requestId = sequenceHeader.requestId;
UA_ByteString_init(&ch->bytes);
LIST_INSERT_HEAD(&channel->chunks, ch, pointers);
}
appendChunkedMessage(ch, msg, pos);
return;
case 'F':
ch = chunkEntryFromRequestId(channel, sequenceHeader.requestId);
if (ch) {
UA_LOG_TRACE(server->config.logger, UA_LOGCATEGORY_SECURECHANNEL, "Final chunk message");
appendChunkedMessage(ch, msg, pos);
bytes = ch->bytes;
LIST_REMOVE(ch, pointers);
UA_free(ch);
final_chunked_pos = *pos;
*pos = 0;
// if the chunks have failed decoding
// message is invalid => return early
if (bytes.length == 0) {
*pos = final_chunked_pos;
return;
}
} else {
bytes = *msg;
}
break;
case 'A':
ch = chunkEntryFromRequestId(channel, sequenceHeader.requestId);
if (ch) {
UA_ByteString_deleteMembers(&ch->bytes);
LIST_REMOVE(ch, pointers);
UA_free(ch);
} else {
UA_LOG_INFO(server->config.logger, UA_LOGCATEGORY_SECURECHANNEL,
"Received MSGA on an unknown request");
}
return;
default:
UA_LOG_INFO(server->config.logger, UA_LOGCATEGORY_SECURECHANNEL,
"Received unknown message chunk: %c", msg->data[*pos - 24 + 3]);
return;
}
retval |= UA_NodeId_decodeBinary(&bytes, pos, &requestTypeId);
if(retval != UA_STATUSCODE_GOOD)
return;
/* Test if the service type nodeid has the right format */
if(requestTypeId.identifierType != UA_NODEIDTYPE_NUMERIC ||
requestTypeId.namespaceIndex != 0) {
UA_NodeId_deleteMembers(&requestTypeId);
sendError(channel, &bytes, *pos, sequenceHeader.requestId, UA_STATUSCODE_BADSERVICEUNSUPPORTED);
return;
}
/* Get the service pointers */
UA_Service service = NULL;
const UA_DataType *requestType = NULL;
const UA_DataType *responseType = NULL;
getServicePointers(requestTypeId.identifier.numeric, &requestType, &responseType, &service);
if(!requestType) {
/* The service is not supported */
if(requestTypeId.identifier.numeric==787)
UA_LOG_INFO(server->config.logger, UA_LOGCATEGORY_SERVER,
"Client requested a subscription, but those are not enabled "
"in the build. The message will be skipped");
else
UA_LOG_INFO(server->config.logger, UA_LOGCATEGORY_SERVER,
"Unknown request: NodeId(ns=%d, i=%d)",
requestTypeId.namespaceIndex, requestTypeId.identifier.numeric);
sendError(channel, &bytes, *pos, sequenceHeader.requestId, UA_STATUSCODE_BADSERVICEUNSUPPORTED);
return;
}
/* Most services can only be called with a valid securechannel */
#ifndef UA_ENABLE_NONSTANDARD_STATELESS
if(channel == &anonymousChannel &&
requestType->typeIndex > UA_TYPES_OPENSECURECHANNELREQUEST) {
sendError(channel, &bytes, *pos, sequenceHeader.requestId, UA_STATUSCODE_BADSECURECHANNELIDINVALID);
return;
}
#endif
/* Decode the request */
void *request = UA_alloca(requestType->memSize);
size_t oldpos = *pos;
retval = UA_decodeBinary(&bytes, pos, request, requestType);
if(retval != UA_STATUSCODE_GOOD) {
sendError(channel, &bytes, oldpos, sequenceHeader.requestId, retval);
return;
}
/* Find the matching session */
UA_Session *session =
UA_SecureChannel_getSession(channel, &((UA_RequestHeader*)request)->authenticationToken);
UA_Session anonymousSession;
if(!session) {
/* session id 0 -> anonymous session */
UA_Session_init(&anonymousSession);
anonymousSession.sessionId = UA_NODEID_NUMERIC(0,0);
anonymousSession.channel = channel;
anonymousSession.activated = true;
session = &anonymousSession;
}
/* Test if the session is valid */
if(!session->activated &&
requestType->typeIndex != UA_TYPES_CREATESESSIONREQUEST &&
requestType->typeIndex != UA_TYPES_ACTIVATESESSIONREQUEST &&
requestType->typeIndex != UA_TYPES_FINDSERVERSREQUEST &&
requestType->typeIndex != UA_TYPES_GETENDPOINTSREQUEST &&
requestType->typeIndex != UA_TYPES_OPENSECURECHANNELREQUEST) {
UA_LOG_INFO(server->config.logger, UA_LOGCATEGORY_SERVER,
"Client tries to call a service with a non-activated session");
sendError(channel, &bytes, *pos, sequenceHeader.requestId, UA_STATUSCODE_BADSESSIONNOTACTIVATED);
return;
}
#ifndef UA_ENABLE_NONSTANDARD_STATELESS
if(session == &anonymousSession &&
requestType->typeIndex != UA_TYPES_CREATESESSIONREQUEST &&
requestType->typeIndex != UA_TYPES_ACTIVATESESSIONREQUEST &&
requestType->typeIndex != UA_TYPES_FINDSERVERSREQUEST &&
requestType->typeIndex != UA_TYPES_GETENDPOINTSREQUEST &&
requestType->typeIndex != UA_TYPES_OPENSECURECHANNELREQUEST) {
#ifdef UA_ENABLE_TYPENAMES
UA_LOG_INFO(server->config.logger, UA_LOGCATEGORY_SERVER,
"Client sent a %s without a session", requestType->typeName);
#else
UA_LOG_INFO(server->config.logger, UA_LOGCATEGORY_SERVER,
"Client tries to call a service without a session");
#endif
sendError(channel, &bytes, *pos, sequenceHeader.requestId, UA_STATUSCODE_BADSESSIONIDINVALID);
return;
}
#endif
UA_Session_updateLifetime(session);
#ifdef UA_ENABLE_SUBSCRIPTIONS
/* The publish request is answered asynchronously */
if(requestTypeId.identifier.numeric - UA_ENCODINGOFFSET_BINARY == UA_NS0ID_PUBLISHREQUEST) {
Service_Publish(server, session, request, sequenceHeader.requestId);
UA_deleteMembers(request, requestType);
return;
}
#endif
/* Call the service */
UA_LOG_DEBUG(server->config.logger, UA_LOGCATEGORY_SERVER,
"Processing a service with type id %u on Session %u",
requestType->typeId.identifier.numeric, session->authenticationToken.identifier.numeric);
UA_assert(service);
UA_assert(requestType);
UA_assert(responseType);
void *response = UA_alloca(responseType->memSize);
UA_init(response, responseType);
init_response_header(request, response);
service(server, session, request, response);
/* Send the response */
retval = UA_SecureChannel_sendBinaryMessage(channel, sequenceHeader.requestId,
response, responseType);
if(retval != UA_STATUSCODE_GOOD) {
/* e.g. UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED */
sendError(channel, &bytes, oldpos, sequenceHeader.requestId, retval);
}
/* Clean up */
if (final_chunked_pos) {
*pos = final_chunked_pos;
UA_ByteString_deleteMembers(&bytes);
}
UA_deleteMembers(request, requestType);
UA_deleteMembers(response, responseType);
return;
}
static void
processCLO(UA_Connection *connection, UA_Server *server, const UA_ByteString *msg, size_t *pos) {
UA_UInt32 secureChannelId;
UA_StatusCode retval = UA_UInt32_decodeBinary(msg, pos, &secureChannelId);
if(retval != UA_STATUSCODE_GOOD || !connection->channel ||
connection->channel->securityToken.channelId != secureChannelId)
return;
Service_CloseSecureChannel(server, secureChannelId);
}
/**
* process binary message received from Connection
* dose not modify UA_ByteString you have to free it youself.
* use of connection->getSendBuffer() and connection->send() to answer Message
*/
void UA_Server_processBinaryMessage(UA_Server *server, UA_Connection *connection, const UA_ByteString *msg) {
size_t pos = 0;
UA_TcpMessageHeader tcpMessageHeader;
do {
if(UA_TcpMessageHeader_decodeBinary(msg, &pos, &tcpMessageHeader)) {
UA_LOG_INFO(server->config.logger, UA_LOGCATEGORY_NETWORK,
"Decoding of message header failed on Connection %i", connection->sockfd);
connection->close(connection);
break;
}
if(tcpMessageHeader.messageSize < 16) {
UA_LOG_INFO(server->config.logger, UA_LOGCATEGORY_NETWORK,
"The message is suspiciously small on Connection %i", connection->sockfd);
connection->close(connection);
break;
}
size_t targetpos = pos - 8 + tcpMessageHeader.messageSize;
switch(tcpMessageHeader.messageTypeAndChunkType & 0x00ffffff) {
case UA_MESSAGETYPE_HEL:
UA_LOG_DEBUG(server->config.logger, UA_LOGCATEGORY_NETWORK,
"Process a HEL on Connection %i", connection->sockfd);
processHEL(connection, msg, &pos);
break;
case UA_MESSAGETYPE_OPN:
processOPN(connection, server, msg, &pos);
break;
case UA_MESSAGETYPE_MSG:
#ifndef UA_ENABLE_NONSTANDARD_STATELESS
if(connection->state != UA_CONNECTION_ESTABLISHED) {
UA_LOG_DEBUG(server->config.logger, UA_LOGCATEGORY_NETWORK,
"Received a MSG where the connection is not established on Connection %i",
connection->sockfd);
connection->close(connection);
return;
}
#endif
UA_LOG_DEBUG(server->config.logger, UA_LOGCATEGORY_NETWORK,
"Process a MSG on Connection %i", connection->sockfd);
processMSG(connection, server, msg, &pos);
break;
case UA_MESSAGETYPE_CLO:
processCLO(connection, server, msg, &pos);
connection->close(connection);
return;
default:
UA_LOG_INFO(server->config.logger, UA_LOGCATEGORY_NETWORK,
"Unknown request type on Connection %i", connection->sockfd);
}
UA_TcpMessageHeader_deleteMembers(&tcpMessageHeader);
if(pos != targetpos) {
UA_LOG_INFO(server->config.logger, UA_LOGCATEGORY_NETWORK,
"Message on Connection %i was not entirely processed. "
"Arrived at position %i, skip after the announced length to position %i",
connection->sockfd, pos, targetpos);
pos = targetpos;
}
} while(msg->length > pos);
}
/*********************************** amalgamated original file "/home/wn/Sources/open62541-open62541-395ce48/src/server/ua_nodes.c" ***********************************/
void UA_Node_deleteMembersAnyNodeClass(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);
UA_Array_delete(node->references, node->referencesSize, &UA_TYPES[UA_TYPES_REFERENCENODE]);
node->references = NULL;
node->referencesSize = 0;
/* 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;
if(p->valueSource == UA_VALUESOURCE_VARIANT)
UA_Variant_deleteMembers(&p->value.variant.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;
dst->instanceHandle = src->instanceHandle;
return UA_STATUSCODE_GOOD;
}
static UA_StatusCode
UA_VariableNode_copy(const UA_VariableNode *src, UA_VariableNode *dst) {
dst->valueRank = src->valueRank;
dst->valueSource = src->valueSource;
if(src->valueSource == UA_VALUESOURCE_VARIANT) {
UA_StatusCode retval = UA_Variant_copy(&src->value.variant.value, &dst->value.variant.value);
if(retval != UA_STATUSCODE_GOOD)
return retval;
dst->value.variant.callback = src->value.variant.callback;
} else
dst->value.dataSource = src->value.dataSource;
dst->accessLevel = src->accessLevel;
dst->userAccessLevel = src->accessLevel;
dst->minimumSamplingInterval = src->minimumSamplingInterval;
dst->historizing = src->historizing;
return UA_STATUSCODE_GOOD;
}
static UA_StatusCode
UA_MethodNode_copy(const UA_MethodNode *src, UA_MethodNode *dst) {
dst->executable = src->executable;
dst->userExecutable = src->userExecutable;
dst->methodHandle = src->methodHandle;
dst->attachedMethod = src->attachedMethod;
return UA_STATUSCODE_GOOD;
}
static UA_StatusCode
UA_ObjectTypeNode_copy(const UA_ObjectTypeNode *src, UA_ObjectTypeNode *dst) {
dst->isAbstract = src->isAbstract;
dst->lifecycleManagement = src->lifecycleManagement;
return UA_STATUSCODE_GOOD;
}
static UA_StatusCode
UA_VariableTypeNode_copy(const UA_VariableTypeNode *src, UA_VariableTypeNode *dst) {
dst->valueRank = src->valueRank;
dst->valueSource = src->valueSource;
if(src->valueSource == UA_VALUESOURCE_VARIANT){
UA_StatusCode retval = UA_Variant_copy(&src->value.variant.value, &dst->value.variant.value);
if(retval != UA_STATUSCODE_GOOD)
return retval;
dst->value.variant.callback = src->value.variant.callback;
} else
dst->value.dataSource = src->value.dataSource;
dst->isAbstract = src->isAbstract;
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_copyAnyNodeClass(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);
dst->nodeClass = src->nodeClass;
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->userWriteMask = src->userWriteMask;
if(retval != UA_STATUSCODE_GOOD) {
UA_Node_deleteMembersAnyNodeClass(dst);
return retval;
}
retval |= UA_Array_copy(src->references, src->referencesSize, (void**)&dst->references,
&UA_TYPES[UA_TYPES_REFERENCENODE]);
if(retval != UA_STATUSCODE_GOOD) {
UA_Node_deleteMembersAnyNodeClass(dst);
return retval;
}
dst->referencesSize = src->referencesSize;
/* 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_deleteMembersAnyNodeClass(dst);
return retval;
}
/*********************************** amalgamated original file "/home/wn/Sources/open62541-open62541-395ce48/src/server/ua_server_worker.c" ***********************************/
/**
* There are four types of job execution:
*
* 1. Normal jobs (dispatched to worker threads if multithreading is activated)
*
* 2. Repeated jobs with a repetition interval (dispatched to worker threads)
*
* 3. Mainloop jobs are executed (once) from the mainloop and not in the worker threads. The server
* contains a stack structure where all threads can add mainloop jobs for the next mainloop
* iteration. This is used e.g. to trigger adding and removing repeated jobs without blocking the
* mainloop.
*
* 4. Delayed jobs are executed once in a worker thread. But only when all normal jobs that were
* dispatched earlier have been executed. This is achieved by a counter in the worker threads. We
* compute from the counter if all previous jobs have finished. The delay can be very long, since we
* try to not interfere too much with normal execution. A use case is to eventually free obsolete
* structures that _could_ still be accessed from concurrent threads.
*
* - Remove the entry from the list
* - mark it as "dead" with an atomic operation
* - add a delayed job that frees the memory when all concurrent operations have completed
*
* This approach to concurrently accessible memory is known as epoch based reclamation [1]. According to
* [2], it performs competitively well on many-core systems. Our version of EBR does however not require
* a global epoch. Instead, every worker thread has its own epoch counter that we observe for changes.
*
* [1] Fraser, K. 2003. Practical lock freedom. Ph.D. thesis. Computer Laboratory, University of Cambridge.
* [2] Hart, T. E., McKenney, P. E., Brown, A. D., & Walpole, J. (2007). Performance of memory reclamation
* for lockless synchronization. Journal of Parallel and Distributed Computing, 67(12), 1270-1285.
*
*
*/
#define MAXTIMEOUT 500 // max timeout in millisec until the next main loop iteration
#define BATCHSIZE 20 // max number of jobs that are dispatched at once to workers
static void processJobs(UA_Server *server, UA_Job *jobs, size_t jobsSize) {
UA_ASSERT_RCU_UNLOCKED();
UA_RCU_LOCK();
for(size_t i = 0; i < jobsSize; i++) {
UA_Job *job = &jobs[i];
switch(job->type) {
case UA_JOBTYPE_NOTHING:
break;
case UA_JOBTYPE_DETACHCONNECTION:
UA_Connection_detachSecureChannel(job->job.closeConnection);
break;
case UA_JOBTYPE_BINARYMESSAGE_NETWORKLAYER:
UA_Server_processBinaryMessage(server, job->job.binaryMessage.connection,
&job->job.binaryMessage.message);
UA_Connection *connection = job->job.binaryMessage.connection;
connection->releaseRecvBuffer(connection, &job->job.binaryMessage.message);
break;
case UA_JOBTYPE_BINARYMESSAGE_ALLOCATED:
UA_Server_processBinaryMessage(server, job->job.binaryMessage.connection,
&job->job.binaryMessage.message);
UA_ByteString_deleteMembers(&job->job.binaryMessage.message);
break;
case UA_JOBTYPE_METHODCALL:
case UA_JOBTYPE_METHODCALL_DELAYED:
job->job.methodCall.method(server, job->job.methodCall.data);
break;
default:
UA_LOG_WARNING(server->config.logger, UA_LOGCATEGORY_SERVER,
"Trying to execute a job of unknown type");
break;
}
}
UA_RCU_UNLOCK();
}
/*******************************/
/* Worker Threads and Dispatch */
/*******************************/
#ifdef UA_ENABLE_MULTITHREADING
struct MainLoopJob {
struct cds_lfs_node node;
UA_Job job;
};
/** Entry in the dispatch queue */
struct DispatchJobsList {
struct cds_wfcq_node node; // node for the queue
size_t jobsSize;
UA_Job *jobs;
};
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 worker */
UA_random_seed((uintptr_t)worker);
rcu_register_thread();
pthread_mutex_t mutex; // required for the condition variable
pthread_mutex_init(&mutex,0);
pthread_mutex_lock(&mutex);
while(*running) {
struct DispatchJobsList *wln = (struct DispatchJobsList*)
cds_wfcq_dequeue_blocking(&server->dispatchQueue_head, &server->dispatchQueue_tail);
if(!wln) {
uatomic_inc(counter);
/* sleep until a work arrives (and wakes up all worker threads) */
pthread_cond_wait(&server->dispatchQueue_condition, &mutex);
continue;
}
processJobs(server, wln->jobs, wln->jobsSize);
UA_free(wln->jobs);
UA_free(wln);
uatomic_inc(counter);
}
pthread_mutex_unlock(&mutex);
pthread_mutex_destroy(&mutex);
UA_ASSERT_RCU_UNLOCKED();
rcu_barrier(); // wait for all scheduled call_rcu work to complete
rcu_unregister_thread();
return NULL;
}
/** Dispatch jobs to workers. Slices the job array up if it contains more than
BATCHSIZE items. The jobs array is freed in the worker threads. */
static void dispatchJobs(UA_Server *server, UA_Job *jobs, size_t jobsSize) {
size_t startIndex = jobsSize; // start at the end
while(jobsSize > 0) {
size_t size = BATCHSIZE;
if(size > jobsSize)
size = jobsSize;
startIndex = startIndex - size;
struct DispatchJobsList *wln = UA_malloc(sizeof(struct DispatchJobsList));
if(startIndex > 0) {
wln->jobs = UA_malloc(size * sizeof(UA_Job));
memcpy(wln->jobs, &jobs[startIndex], size * sizeof(UA_Job));
wln->jobsSize = size;
} else {
/* forward the original array */
wln->jobsSize = size;
wln->jobs = jobs;
}
cds_wfcq_node_init(&wln->node);
cds_wfcq_enqueue(&server->dispatchQueue_head, &server->dispatchQueue_tail, &wln->node);
jobsSize -= size;
}
}
static void
emptyDispatchQueue(UA_Server *server) {
while(!cds_wfcq_empty(&server->dispatchQueue_head, &server->dispatchQueue_tail)) {
struct DispatchJobsList *wln = (struct DispatchJobsList*)
cds_wfcq_dequeue_blocking(&server->dispatchQueue_head, &server->dispatchQueue_tail);
processJobs(server, wln->jobs, wln->jobsSize);
UA_free(wln->jobs);
UA_free(wln);
}
}
#endif
/*****************/
/* Repeated Jobs */
/*****************/
struct IdentifiedJob {
UA_Job job;
UA_Guid id;
};
/**
* The RepeatedJobs structure contains an array of jobs that are either executed with the same
* repetition interval. The linked list is sorted, so we can stop traversing when the first element
* has nextTime > now.
*/
struct RepeatedJobs {
LIST_ENTRY(RepeatedJobs) pointers; ///> Links to the next list of repeated jobs (with a different) interval
UA_DateTime nextTime; ///> The next time when the jobs are to be executed
UA_UInt32 interval; ///> Interval in 100ns resolution
size_t jobsSize; ///> Number of jobs contained
struct IdentifiedJob jobs[]; ///> The jobs. This is not a pointer, instead the struct is variable sized.
};
/* throwaway struct for the mainloop callback */
struct AddRepeatedJob {
struct IdentifiedJob job;
UA_UInt32 interval;
};
/* internal. call only from the main loop. */
static UA_StatusCode addRepeatedJob(UA_Server *server, struct AddRepeatedJob * UA_RESTRICT arw) {
struct RepeatedJobs *matchingTw = NULL; // add the item here
struct RepeatedJobs *lastTw = NULL; // if there is no repeated job, add a new one this entry
struct RepeatedJobs *tempTw;
UA_StatusCode retval = UA_STATUSCODE_GOOD;
/* search for matching entry */
UA_DateTime firstTime = UA_DateTime_nowMonotonic();
tempTw = LIST_FIRST(&server->repeatedJobs);
while(tempTw) {
if(arw->interval == tempTw->interval) {
matchingTw = tempTw;
break;
}
if(tempTw->nextTime > firstTime)
break;
lastTw = tempTw;
tempTw = LIST_NEXT(lastTw, pointers);
}
if(matchingTw) {
/* append to matching entry */
matchingTw = UA_realloc(matchingTw, sizeof(struct RepeatedJobs) +
(sizeof(struct IdentifiedJob) * (matchingTw->jobsSize + 1)));
if(!matchingTw) {
retval = UA_STATUSCODE_BADOUTOFMEMORY;
goto cleanup;
}
/* link the reallocated tw into the list */
LIST_REPLACE(matchingTw, matchingTw, pointers);
} else {
/* create a new entry */
matchingTw = UA_malloc(sizeof(struct RepeatedJobs) + sizeof(struct IdentifiedJob));
if(!matchingTw) {
retval = UA_STATUSCODE_BADOUTOFMEMORY;
goto cleanup;
}
matchingTw->jobsSize = 0;
matchingTw->nextTime = firstTime;
matchingTw->interval = arw->interval;
if(lastTw)
LIST_INSERT_AFTER(lastTw, matchingTw, pointers);
else
LIST_INSERT_HEAD(&server->repeatedJobs, matchingTw, pointers);
}
matchingTw->jobs[matchingTw->jobsSize] = arw->job;
matchingTw->jobsSize++;
cleanup:
#ifdef UA_ENABLE_MULTITHREADING
UA_free(arw);
#endif
return retval;
}
UA_StatusCode UA_Server_addRepeatedJob(UA_Server *server, UA_Job job, UA_UInt32 interval, UA_Guid *jobId) {
/* the interval needs to be at least 5ms */
if(interval < 5)
return UA_STATUSCODE_BADINTERNALERROR;
interval *= (UA_UInt32)UA_MSEC_TO_DATETIME; // from ms to 100ns resolution
#ifdef UA_ENABLE_MULTITHREADING
struct AddRepeatedJob *arw = UA_malloc(sizeof(struct AddRepeatedJob));
if(!arw)
return UA_STATUSCODE_BADOUTOFMEMORY;
arw->interval = interval;
arw->job.job = job;
if(jobId) {
arw->job.id = UA_Guid_random();
*jobId = arw->job.id;
} else
UA_Guid_init(&arw->job.id);
struct MainLoopJob *mlw = UA_malloc(sizeof(struct MainLoopJob));
if(!mlw) {
UA_free(arw);
return UA_STATUSCODE_BADOUTOFMEMORY;
}
mlw->job = (UA_Job) {
.type = UA_JOBTYPE_METHODCALL,
.job.methodCall = {.data = arw, .method = (void (*)(UA_Server*, void*))addRepeatedJob}};
cds_lfs_push(&server->mainLoopJobs, &mlw->node);
#else
struct AddRepeatedJob arw;
arw.interval = interval;
arw.job.job = job;
if(jobId) {
arw.job.id = UA_Guid_random();
*jobId = arw.job.id;
} else
UA_Guid_init(&arw.job.id);
addRepeatedJob(server, &arw);
#endif
return UA_STATUSCODE_GOOD;
}
/* Returns the next datetime when a repeated job is scheduled */
static UA_DateTime processRepeatedJobs(UA_Server *server, UA_DateTime current) {
struct RepeatedJobs *tw, *tmp_tw;
/* Iterate over the list of elements (sorted according to the next execution timestamp) */
LIST_FOREACH_SAFE(tw, &server->repeatedJobs, pointers, tmp_tw) {
if(tw->nextTime > current)
break;
#ifdef UA_ENABLE_MULTITHREADING
// copy the entry and insert at the new location
UA_Job *jobsCopy = UA_malloc(sizeof(UA_Job) * tw->jobsSize);
if(!jobsCopy) {
UA_LOG_ERROR(server->config.logger, UA_LOGCATEGORY_SERVER,
"Not enough memory to dispatch delayed jobs");
break;
}
for(size_t i=0;i<tw->jobsSize;i++)
jobsCopy[i] = tw->jobs[i].job;
dispatchJobs(server, jobsCopy, tw->jobsSize); // frees the job pointer
#else
size_t size = tw->jobsSize;
for(size_t i = 0; i < size; i++)
processJobs(server, &tw->jobs[i].job, 1); // does not free the job ptr
#endif
/* Elements are removed only here. Check if empty. */
if(tw->jobsSize == 0) {
LIST_REMOVE(tw, pointers);
UA_free(tw);
UA_assert(LIST_FIRST(&server->repeatedJobs) != tw); /* Assert for static code checkers */
continue;
}
/* Set the time for the next execution */
tw->nextTime += tw->interval;
if(tw->nextTime < current)
tw->nextTime = current;
/* Reinsert to keep the list sorted */
struct RepeatedJobs *prevTw = LIST_FIRST(&server->repeatedJobs);
while(true) {
struct RepeatedJobs *n = LIST_NEXT(prevTw, pointers);
if(!n || n->nextTime > tw->nextTime)
break;
prevTw = n;
}
if(prevTw != tw) {
LIST_REMOVE(tw, pointers);
LIST_INSERT_AFTER(prevTw, tw, pointers);
}
}
// check if the next repeated job is sooner than the usual timeout
// calc in 32 bit must be ok
struct RepeatedJobs *first = LIST_FIRST(&server->repeatedJobs);
UA_DateTime next = current + (MAXTIMEOUT * UA_MSEC_TO_DATETIME);
if(first && first->nextTime < next)
next = first->nextTime;
return next;
}
/* Call this function only from the main loop! */
static void removeRepeatedJob(UA_Server *server, UA_Guid *jobId) {
struct RepeatedJobs *tw;
LIST_FOREACH(tw, &server->repeatedJobs, pointers) {
for(size_t i = 0; i < tw->jobsSize; i++) {
if(!UA_Guid_equal(jobId, &tw->jobs[i].id))
continue;
tw->jobsSize--; /* if size == 0, tw is freed during the next processing */
if(tw->jobsSize > 0)
tw->jobs[i] = tw->jobs[tw->jobsSize]; // move the last entry to overwrite
goto finish;
}
}
finish:
#ifdef UA_ENABLE_MULTITHREADING
UA_free(jobId);
#endif
return;
}
UA_StatusCode UA_Server_removeRepeatedJob(UA_Server *server, UA_Guid jobId) {
#ifdef UA_ENABLE_MULTITHREADING
UA_Guid *idptr = UA_malloc(sizeof(UA_Guid));
if(!idptr)
return UA_STATUSCODE_BADOUTOFMEMORY;
*idptr = jobId;
// dispatch to the mainloopjobs stack
struct MainLoopJob *mlw = UA_malloc(sizeof(struct MainLoopJob));
mlw->job = (UA_Job) {
.type = UA_JOBTYPE_METHODCALL,
.job.methodCall = {.data = idptr, .method = (void (*)(UA_Server*, void*))removeRepeatedJob}};
cds_lfs_push(&server->mainLoopJobs, &mlw->node);
#else
removeRepeatedJob(server, &jobId);
#endif
return UA_STATUSCODE_GOOD;
}
void UA_Server_deleteAllRepeatedJobs(UA_Server *server) {
struct RepeatedJobs *current, *temp;
LIST_FOREACH_SAFE(current, &server->repeatedJobs, pointers, temp) {
LIST_REMOVE(current, pointers);
UA_free(current);
}
}
/****************/
/* Delayed Jobs */
/****************/
#ifdef UA_ENABLE_MULTITHREADING
#define DELAYEDJOBSSIZE 100 // Collect delayed jobs until we have DELAYEDWORKSIZE items
struct DelayedJobs {
struct DelayedJobs *next;
UA_UInt32 *workerCounters; // initially NULL until the counter are set
UA_UInt32 jobsCount; // the size of the array is DELAYEDJOBSSIZE, the count may be less
UA_Job jobs[DELAYEDJOBSSIZE]; // when it runs full, a new delayedJobs entry is created
};
/* Dispatched as an ordinary job when the DelayedJobs list is full */
static void getCounters(UA_Server *server, struct DelayedJobs *delayed) {
UA_UInt32 *counters = UA_malloc(server->config.nThreads * sizeof(UA_UInt32));
for(UA_UInt16 i = 0; i < server->config.nThreads; i++)
counters[i] = server->workers[i].counter;
delayed->workerCounters = counters;
}
// Call from the main thread only. This is the only function that modifies
// server->delayedWork. processDelayedWorkQueue modifies the "next" (after the
// head).
static void addDelayedJob(UA_Server *server, UA_Job *job) {
struct DelayedJobs *dj = server->delayedJobs;
if(!dj || dj->jobsCount >= DELAYEDJOBSSIZE) {
/* create a new DelayedJobs and add it to the linked list */
dj = UA_malloc(sizeof(struct DelayedJobs));
if(!dj) {
UA_LOG_ERROR(server->config.logger, UA_LOGCATEGORY_SERVER,
"Not enough memory to add a delayed job");
return;
}
dj->jobsCount = 0;
dj->workerCounters = NULL;
dj->next = server->delayedJobs;
server->delayedJobs = dj;
/* dispatch a method that sets the counter for the full list that comes afterwards */
if(dj->next) {
UA_Job *setCounter = UA_malloc(sizeof(UA_Job));
*setCounter = (UA_Job) {.type = UA_JOBTYPE_METHODCALL, .job.methodCall =
{.method = (void (*)(UA_Server*, void*))getCounters, .data = dj->next}};
dispatchJobs(server, setCounter, 1);
}
}
dj->jobs[dj->jobsCount] = *job;
dj->jobsCount++;
}
static void addDelayedJobAsync(UA_Server *server, UA_Job *job) {
addDelayedJob(server, job);
UA_free(job);
}
static void server_free(UA_Server *server, void *data) {
UA_free(data);
}
UA_StatusCode UA_Server_delayedFree(UA_Server *server, void *data) {
UA_Job *j = UA_malloc(sizeof(UA_Job));
if(!j)
return UA_STATUSCODE_BADOUTOFMEMORY;
j->type = UA_JOBTYPE_METHODCALL;
j->job.methodCall.data = data;
j->job.methodCall.method = server_free;
struct MainLoopJob *mlw = UA_malloc(sizeof(struct MainLoopJob));
mlw->job = (UA_Job) {.type = UA_JOBTYPE_METHODCALL, .job.methodCall =
{.data = j, .method = (UA_ServerCallback)addDelayedJobAsync}};
cds_lfs_push(&server->mainLoopJobs, &mlw->node);
return UA_STATUSCODE_GOOD;
}
UA_StatusCode
UA_Server_delayedCallback(UA_Server *server, UA_ServerCallback callback, void *data) {
UA_Job *j = UA_malloc(sizeof(UA_Job));
if(!j)
return UA_STATUSCODE_BADOUTOFMEMORY;
j->type = UA_JOBTYPE_METHODCALL;
j->job.methodCall.data = data;
j->job.methodCall.method = callback;
struct MainLoopJob *mlw = UA_malloc(sizeof(struct MainLoopJob));
mlw->job = (UA_Job) {.type = UA_JOBTYPE_METHODCALL, .job.methodCall =
{.data = j, .method = (UA_ServerCallback)addDelayedJobAsync}};
cds_lfs_push(&server->mainLoopJobs, &mlw->node);
return UA_STATUSCODE_GOOD;
}
/* Find out which delayed jobs can be executed now */
static void
dispatchDelayedJobs(UA_Server *server, void *_) {
/* start at the second */
struct DelayedJobs *dw = server->delayedJobs, *beforedw = dw;
if(dw)
dw = dw->next;
/* find the first delayedwork where the counters have been set and have moved */
while(dw) {
if(!dw->workerCounters) {
beforedw = dw;
dw = dw->next;
continue;
}
UA_Boolean allMoved = true;
for(size_t i = 0; i < server->config.nThreads; i++) {
if(dw->workerCounters[i] == server->workers[i].counter) {
allMoved = false;
break;
}
}
if(allMoved)
break;
beforedw = dw;
dw = dw->next;
}
#if (__GNUC__ <= 4 && __GNUC_MINOR__ <= 6)
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wextra"
#pragma GCC diagnostic ignored "-Wcast-qual"
#pragma GCC diagnostic ignored "-Wunused-value"
#endif
/* process and free all delayed jobs from here on */
while(dw) {
processJobs(server, dw->jobs, dw->jobsCount);
struct DelayedJobs *next = uatomic_xchg(&beforedw->next, NULL);
UA_free(dw);
UA_free(dw->workerCounters);
dw = next;
}
#if (__GNUC__ <= 4 && __GNUC_MINOR__ <= 6)
#pragma GCC diagnostic pop
#endif
}
#endif
/********************/
/* Main Server Loop */
/********************/
#ifdef UA_ENABLE_MULTITHREADING
static void processMainLoopJobs(UA_Server *server) {
/* no synchronization required if we only use push and pop_all */
struct cds_lfs_head *head = __cds_lfs_pop_all(&server->mainLoopJobs);
if(!head)
return;
struct MainLoopJob *mlw = (struct MainLoopJob*)&head->node;
struct MainLoopJob *next;
do {
processJobs(server, &mlw->job, 1);
next = (struct MainLoopJob*)mlw->node.next;
UA_free(mlw);
//cppcheck-suppress unreadVariable
} while((mlw = next));
//UA_free(head);
}
#endif
UA_StatusCode UA_Server_run_startup(UA_Server *server) {
#ifdef UA_ENABLE_MULTITHREADING
/* Spin up the worker threads */
UA_LOG_INFO(server->config.logger, UA_LOGCATEGORY_SERVER,
"Spinning up %u worker thread(s)", server->config.nThreads);
pthread_cond_init(&server->dispatchQueue_condition, 0);
server->workers = 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);
}
/* Try to execute delayed callbacks every 10 sec */
UA_Job processDelayed = {.type = UA_JOBTYPE_METHODCALL,
.job.methodCall = {.method = dispatchDelayedJobs, .data = NULL} };
UA_Server_addRepeatedJob(server, processDelayed, 10000, NULL);
#endif
/* Start the networklayers */
UA_StatusCode result = UA_STATUSCODE_GOOD;
for(size_t i = 0; i < server->config.networkLayersSize; i++) {
UA_ServerNetworkLayer *nl = &server->config.networkLayers[i];
result |= nl->start(nl, server->config.logger);
for(size_t j = 0; j < server->endpointDescriptionsSize; j++) {
UA_String_copy(&nl->discoveryUrl, &server->endpointDescriptions[j].endpointUrl);
}
}
return result;
}
static void completeMessages(UA_Server *server, UA_Job *job) {
UA_Boolean realloced = UA_FALSE;
UA_StatusCode retval = UA_Connection_completeMessages(job->job.binaryMessage.connection,
&job->job.binaryMessage.message, &realloced);
if(retval != UA_STATUSCODE_GOOD) {
if(retval == UA_STATUSCODE_BADOUTOFMEMORY)
UA_LOG_WARNING(server->config.logger, UA_LOGCATEGORY_NETWORK,
"Lost message(s) from Connection %i as memory could not be allocated",
job->job.binaryMessage.connection->sockfd);
else if(retval != UA_STATUSCODE_GOOD)
UA_LOG_INFO(server->config.logger, UA_LOGCATEGORY_NETWORK,
"Could not merge half-received messages on Connection %i with error 0x%08x",
job->job.binaryMessage.connection->sockfd, retval);
job->type = UA_JOBTYPE_NOTHING;
return;
}
if(realloced)
job->type = UA_JOBTYPE_BINARYMESSAGE_ALLOCATED;
}
UA_UInt16 UA_Server_run_iterate(UA_Server *server, UA_Boolean waitInternal) {
#ifdef UA_ENABLE_MULTITHREADING
/* Run work assigned for the main thread */
processMainLoopJobs(server);
#endif
/* Process repeated work */
UA_DateTime now = UA_DateTime_nowMonotonic();
UA_DateTime nextRepeated = processRepeatedJobs(server, now);
UA_UInt16 timeout = 0;
if(waitInternal)
timeout = (UA_UInt16)((nextRepeated - now) / UA_MSEC_TO_DATETIME);
/* Get work from the networklayer */
for(size_t i = 0; i < server->config.networkLayersSize; i++) {
UA_ServerNetworkLayer *nl = &server->config.networkLayers[i];
UA_Job *jobs;
size_t jobsSize;
/* only the last networklayer waits on the tieout */
if(i == server->config.networkLayersSize-1)
jobsSize = nl->getJobs(nl, &jobs, timeout);
else
jobsSize = nl->getJobs(nl, &jobs, 0);
for(size_t k = 0; k < jobsSize; k++) {
#ifdef UA_ENABLE_MULTITHREADING
/* Filter out delayed work */
if(jobs[k].type == UA_JOBTYPE_METHODCALL_DELAYED) {
addDelayedJob(server, &jobs[k]);
jobs[k].type = UA_JOBTYPE_NOTHING;
continue;
}
#endif
/* Merge half-received messages */
if(jobs[k].type == UA_JOBTYPE_BINARYMESSAGE_NETWORKLAYER)
completeMessages(server, &jobs[k]);
}
#ifdef UA_ENABLE_MULTITHREADING
dispatchJobs(server, jobs, jobsSize);
/* Wake up worker threads */
if(jobsSize > 0)
pthread_cond_broadcast(&server->dispatchQueue_condition);
#else
processJobs(server, jobs, jobsSize);
if(jobsSize > 0)
UA_free(jobs);
#endif
}
now = UA_DateTime_nowMonotonic();
timeout = 0;
if(nextRepeated > now)
timeout = (UA_UInt16)((nextRepeated - now) / UA_MSEC_TO_DATETIME);
return timeout;
}
UA_StatusCode UA_Server_run_shutdown(UA_Server *server) {
for(size_t i = 0; i < server->config.networkLayersSize; i++) {
UA_ServerNetworkLayer *nl = &server->config.networkLayers[i];
UA_Job *stopJobs;
size_t stopJobsSize = nl->stop(nl, &stopJobs);
processJobs(server, stopJobs, stopJobsSize);
UA_free(stopJobs);
}
#ifdef UA_ENABLE_MULTITHREADING
UA_LOG_INFO(server->config.logger, UA_LOGCATEGORY_SERVER,
"Shutting down %u worker thread(s)", server->config.nThreads);
/* Wait for all worker threads to finish */
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);
/* Manually finish the work still enqueued.
This especially contains delayed frees */
emptyDispatchQueue(server);
UA_ASSERT_RCU_UNLOCKED();
rcu_barrier(); // wait for all scheduled call_rcu work to complete
#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;
while(*running)
UA_Server_run_iterate(server, true);
return UA_Server_run_shutdown(server);
}
/*********************************** amalgamated original file "/home/wn/Sources/open62541-open62541-395ce48/src/server/ua_securechannel_manager.c" ***********************************/
UA_StatusCode
UA_SecureChannelManager_init(UA_SecureChannelManager *cm, size_t maxChannelCount,
UA_UInt32 tokenLifetime, UA_UInt32 startChannelId,
UA_UInt32 startTokenId, UA_Server *server) {
LIST_INIT(&cm->channels);
cm->lastChannelId = startChannelId;
cm->lastTokenId = startTokenId;
cm->maxChannelLifetime = tokenLifetime;
cm->maxChannelCount = maxChannelCount;
cm->currentChannelCount = 0;
cm->server = server;
return UA_STATUSCODE_GOOD;
}
void UA_SecureChannelManager_deleteMembers(UA_SecureChannelManager *cm) {
channel_list_entry *entry, *temp;
LIST_FOREACH_SAFE(entry, &cm->channels, pointers, temp) {
LIST_REMOVE(entry, pointers);
UA_SecureChannel_deleteMembersCleanup(&entry->channel);
UA_free(entry);
}
}
/* remove channels that were not renewed or who have no connection attached */
void UA_SecureChannelManager_cleanupTimedOut(UA_SecureChannelManager *cm, UA_DateTime now) {
channel_list_entry *entry, *temp;
LIST_FOREACH_SAFE(entry, &cm->channels, pointers, temp) {
UA_DateTime timeout =
entry->channel.securityToken.createdAt +
(UA_DateTime)(entry->channel.securityToken.revisedLifetime * UA_MSEC_TO_DATETIME);
if(timeout < now || !entry->channel.connection) {
UA_LOG_DEBUG(cm->server->config.logger, UA_LOGCATEGORY_SECURECHANNEL,
"SecureChannel %i has timed out", entry->channel.securityToken.channelId);
LIST_REMOVE(entry, pointers);
UA_SecureChannel_deleteMembersCleanup(&entry->channel);
#ifndef UA_ENABLE_MULTITHREADING
cm->currentChannelCount--;
UA_free(entry);
#else
cm->currentChannelCount = uatomic_add_return(&cm->currentChannelCount, -1);
UA_Server_delayedFree(cm->server, entry);
#endif
} else if(entry->channel.nextSecurityToken.tokenId > 0) {
UA_SecureChannel_revolveTokens(&entry->channel);
}
}
}
UA_StatusCode
UA_SecureChannelManager_open(UA_SecureChannelManager *cm, UA_Connection *conn,
const UA_OpenSecureChannelRequest *request,
UA_OpenSecureChannelResponse *response) {
if(request->securityMode != UA_MESSAGESECURITYMODE_NONE)
return UA_STATUSCODE_BADSECURITYMODEREJECTED;
if(cm->currentChannelCount >= cm->maxChannelCount)
return UA_STATUSCODE_BADOUTOFMEMORY;
channel_list_entry *entry = UA_malloc(sizeof(channel_list_entry));
if(!entry)
return UA_STATUSCODE_BADOUTOFMEMORY;
#ifndef UA_ENABLE_MULTITHREADING
cm->currentChannelCount++;
#else
cm->currentChannelCount = uatomic_add_return(&cm->currentChannelCount, 1);
#endif
UA_SecureChannel_init(&entry->channel);
response->responseHeader.stringTableSize = 0;
response->responseHeader.timestamp = UA_DateTime_now();
response->serverProtocolVersion = 0;
entry->channel.securityToken.channelId = cm->lastChannelId++;
entry->channel.securityToken.tokenId = cm->lastTokenId++;
entry->channel.securityToken.createdAt = UA_DateTime_now();
entry->channel.securityToken.revisedLifetime =
(request->requestedLifetime > cm->maxChannelLifetime) ?
cm->maxChannelLifetime : request->requestedLifetime;
/* pragmatic workaround to get clients requesting lifetime of 0 working */
if(entry->channel.securityToken.revisedLifetime == 0)
entry->channel.securityToken.revisedLifetime = cm->maxChannelLifetime;
UA_ByteString_copy(&request->clientNonce, &entry->channel.clientNonce);
entry->channel.serverAsymAlgSettings.securityPolicyUri = UA_STRING_ALLOC(
"http://opcfoundation.org/UA/SecurityPolicy#None");
UA_SecureChannel_generateNonce(&entry->channel.serverNonce);
UA_ByteString_copy(&entry->channel.serverNonce, &response->serverNonce);
UA_ChannelSecurityToken_copy(&entry->channel.securityToken,
&response->securityToken);
UA_Connection_attachSecureChannel(conn, &entry->channel);
LIST_INSERT_HEAD(&cm->channels, entry, pointers);
return UA_STATUSCODE_GOOD;
}
UA_StatusCode
UA_SecureChannelManager_renew(UA_SecureChannelManager *cm, UA_Connection *conn,
const UA_OpenSecureChannelRequest *request,
UA_OpenSecureChannelResponse *response) {
UA_SecureChannel *channel = conn->channel;
if(!channel)
return UA_STATUSCODE_BADINTERNALERROR;
/* if no security token is already issued */
if(channel->nextSecurityToken.tokenId == 0) {
channel->nextSecurityToken.channelId = channel->securityToken.channelId;
//FIXME: UaExpert seems not to use the new tokenid
channel->nextSecurityToken.tokenId = cm->lastTokenId++;
//channel->nextSecurityToken.tokenId = channel->securityToken.tokenId;
channel->nextSecurityToken.createdAt = UA_DateTime_now();
channel->nextSecurityToken.revisedLifetime =
(request->requestedLifetime > cm->maxChannelLifetime) ?
cm->maxChannelLifetime : request->requestedLifetime;
/* pragmatic workaround to get clients requesting lifetime of 0 working */
if(channel->nextSecurityToken.revisedLifetime == 0)
channel->nextSecurityToken.revisedLifetime = cm->maxChannelLifetime;
}
if(channel->clientNonce.data)
UA_ByteString_deleteMembers(&channel->clientNonce);
UA_ByteString_copy(&request->clientNonce, &channel->clientNonce);
UA_ByteString_copy(&channel->serverNonce, &response->serverNonce);
UA_ChannelSecurityToken_copy(&channel->nextSecurityToken, &response->securityToken);
return UA_STATUSCODE_GOOD;
}
UA_SecureChannel * UA_SecureChannelManager_get(UA_SecureChannelManager *cm, UA_UInt32 channelId) {
channel_list_entry *entry;
LIST_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_list_entry *entry;
LIST_FOREACH(entry, &cm->channels, pointers) {
if(entry->channel.securityToken.channelId == channelId) {
LIST_REMOVE(entry, pointers);
UA_SecureChannel_deleteMembersCleanup(&entry->channel);
#ifndef UA_ENABLE_MULTITHREADING
cm->currentChannelCount--;
UA_free(entry);
#else
cm->currentChannelCount = uatomic_add_return(&cm->currentChannelCount, -1);
UA_Server_delayedFree(cm->server, entry);
#endif
return UA_STATUSCODE_GOOD;
}
}
return UA_STATUSCODE_BADINTERNALERROR;
}
/*********************************** amalgamated original file "/home/wn/Sources/open62541-open62541-395ce48/src/server/ua_session_manager.c" ***********************************/
UA_StatusCode
UA_SessionManager_init(UA_SessionManager *sm, UA_UInt32 maxSessionCount,
UA_UInt32 maxSessionLifeTime, UA_UInt32 startSessionId,
UA_Server *server) {
LIST_INIT(&sm->sessions);
sm->maxSessionCount = maxSessionCount;
sm->lastSessionId = startSessionId;
sm->maxSessionLifeTime = maxSessionLifeTime;
sm->currentSessionCount = 0;
sm->server = server;
return UA_STATUSCODE_GOOD;
}
void UA_SessionManager_deleteMembers(UA_SessionManager *sm) {
session_list_entry *current, *temp;
LIST_FOREACH_SAFE(current, &sm->sessions, pointers, temp) {
LIST_REMOVE(current, pointers);
UA_Session_deleteMembersCleanup(&current->session, sm->server);
UA_free(current);
}
}
void UA_SessionManager_cleanupTimedOut(UA_SessionManager *sm, UA_DateTime now) {
session_list_entry *sentry, *temp;
LIST_FOREACH_SAFE(sentry, &sm->sessions, pointers, temp) {
if(sentry->session.validTill < now) {
UA_LOG_DEBUG(sm->server->config.logger, UA_LOGCATEGORY_SESSION,
"Session with token %i has timed out and is removed",
sentry->session.sessionId.identifier.numeric);
LIST_REMOVE(sentry, pointers);
UA_Session_deleteMembersCleanup(&sentry->session, sm->server);
#ifndef UA_ENABLE_MULTITHREADING
sm->currentSessionCount--;
UA_free(sentry);
#else
sm->currentSessionCount = uatomic_add_return(&sm->currentSessionCount, -1);
UA_Server_delayedFree(sm->server, sentry);
#endif
}
}
}
UA_Session *
UA_SessionManager_getSession(UA_SessionManager *sm, const UA_NodeId *token) {
session_list_entry *current = NULL;
LIST_FOREACH(current, &sm->sessions, pointers) {
if(UA_NodeId_equal(&current->session.authenticationToken, token)) {
if(UA_DateTime_now() > current->session.validTill) {
UA_LOG_DEBUG(sm->server->config.logger, UA_LOGCATEGORY_SESSION,
"Try to use Session with token %i, but has timed out", token->identifier.numeric);
return NULL;
}
return &current->session;
}
}
UA_LOG_DEBUG(sm->server->config.logger, UA_LOGCATEGORY_SESSION,
"Try to use Session with token %i but is not found", token->identifier.numeric);
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->maxSessionCount)
return UA_STATUSCODE_BADTOOMANYSESSIONS;
session_list_entry *newentry = UA_malloc(sizeof(session_list_entry));
if(!newentry)
return UA_STATUSCODE_BADOUTOFMEMORY;
sm->currentSessionCount++;
UA_Session_init(&newentry->session);
newentry->session.sessionId = UA_NODEID_NUMERIC(1, sm->lastSessionId++);
newentry->session.authenticationToken = UA_NODEID_GUID(1, UA_Guid_random());
if(request->requestedSessionTimeout <= sm->maxSessionLifeTime &&
request->requestedSessionTimeout > 0)
newentry->session.timeout = request->requestedSessionTimeout;
else
newentry->session.timeout = sm->maxSessionLifeTime; // todo: remove when the CTT is fixed
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.authenticationToken, token))
break;
}
if(!current)
return UA_STATUSCODE_BADSESSIONIDINVALID;
LIST_REMOVE(current, pointers);
UA_Session_deleteMembersCleanup(&current->session, sm->server);
#ifndef UA_ENABLE_MULTITHREADING
sm->currentSessionCount--;
UA_free(current);
#else
sm->currentSessionCount = uatomic_add_return(&sm->currentSessionCount, -1);
UA_Server_delayedFree(sm->server, current);
#endif
return UA_STATUSCODE_GOOD;
}
/*********************************** amalgamated original file "/home/wn/Sources/open62541-open62541-395ce48/src/server/ua_services_discovery.c" ***********************************/
void Service_FindServers(UA_Server *server, UA_Session *session,
const UA_FindServersRequest *request, UA_FindServersResponse *response) {
/* copy ApplicationDescription from the config */
UA_ApplicationDescription *descr = UA_malloc(sizeof(UA_ApplicationDescription));
if(!descr) {
response->responseHeader.serviceResult = UA_STATUSCODE_BADOUTOFMEMORY;
return;
}
response->responseHeader.serviceResult =
UA_ApplicationDescription_copy(&server->config.applicationDescription, descr);
if(response->responseHeader.serviceResult != UA_STATUSCODE_GOOD) {
UA_free(descr);
return;
}
/* add the discoveryUrls from the networklayers */
UA_String *disc = UA_realloc(descr->discoveryUrls, sizeof(UA_String) *
(descr->discoveryUrlsSize + server->config.networkLayersSize));
if(!disc) {
response->responseHeader.serviceResult = UA_STATUSCODE_BADOUTOFMEMORY;
UA_ApplicationDescription_delete(descr);
return;
}
size_t existing = descr->discoveryUrlsSize;
descr->discoveryUrls = disc;
descr->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, &descr->discoveryUrls[existing + i]);
}
response->servers = descr;
response->serversSize = 1;
}
void Service_GetEndpoints(UA_Server *server, UA_Session *session, const UA_GetEndpointsRequest *request,
UA_GetEndpointsResponse *response) {
/* Test if one of the networklayers exposes the discoveryUrl of the requested endpoint */
/* Disabled, servers in a virtualbox don't know their external hostname */
/* UA_Boolean foundUri = false; */
/* for(size_t i = 0; i < server->config.networkLayersSize; i++) { */
/* if(UA_String_equal(&request->endpointUrl, &server->config.networkLayers[i].discoveryUrl)) { */
/* foundUri = true; */
/* break; */
/* } */
/* } */
/* if(!foundUri) { */
/* response->endpointsSize = 0; */
/* return; */
/* } */
/* test if the supported binary profile shall be returned */
#ifdef NO_ALLOCA
UA_Boolean relevant_endpoints[server->endpointDescriptionsSize];
#else
UA_Boolean *relevant_endpoints = UA_alloca(sizeof(UA_Byte) * server->endpointDescriptionsSize);
#endif
size_t relevant_count = 0;
for(size_t j = 0; j < server->endpointDescriptionsSize; j++) {
relevant_endpoints[j] = false;
if(request->profileUrisSize == 0) {
relevant_endpoints[j] = true;
relevant_count++;
continue;
}
for(size_t i = 0; i < request->profileUrisSize; i++) {
if(UA_String_equal(&request->profileUris[i], &server->endpointDescriptions->transportProfileUri)) {
relevant_endpoints[j] = true;
relevant_count++;
break;
}
}
}
if(relevant_count == 0) {
response->endpointsSize = 0;
return;
}
response->endpoints = UA_malloc(sizeof(UA_EndpointDescription) * relevant_count);
if(!response->endpoints) {
response->responseHeader.serviceResult = UA_STATUSCODE_BADOUTOFMEMORY;
return;
}
size_t k = 0;
UA_StatusCode retval = UA_STATUSCODE_GOOD;
for(size_t j = 0; j < server->endpointDescriptionsSize && retval == UA_STATUSCODE_GOOD; j++) {
if(!relevant_endpoints[j])
continue;
retval = UA_EndpointDescription_copy(&server->endpointDescriptions[j], &response->endpoints[k]);
if(retval != UA_STATUSCODE_GOOD)
break;
UA_String_deleteMembers(&response->endpoints[k].endpointUrl);
retval = UA_String_copy(&request->endpointUrl, &response->endpoints[k].endpointUrl);
k++;
}
if(retval != UA_STATUSCODE_GOOD) {
response->responseHeader.serviceResult = retval;
UA_Array_delete(response->endpoints, --k, &UA_TYPES[UA_TYPES_ENDPOINTDESCRIPTION]);
return;
}
response->endpointsSize = relevant_count;
}
/*********************************** amalgamated original file "/home/wn/Sources/open62541-open62541-395ce48/src/server/ua_services_securechannel.c" ***********************************/
void Service_OpenSecureChannel(UA_Server *server, UA_Connection *connection,
const UA_OpenSecureChannelRequest *request,
UA_OpenSecureChannelResponse *response) {
// todo: if(request->clientProtocolVersion != protocolVersion)
if(request->requestType == UA_SECURITYTOKENREQUESTTYPE_ISSUE) {
response->responseHeader.serviceResult =
UA_SecureChannelManager_open(&server->secureChannelManager, connection, request, response);
if(response->responseHeader.serviceResult == UA_STATUSCODE_GOOD)
UA_LOG_DEBUG(server->config.logger, UA_LOGCATEGORY_SECURECHANNEL,
"Opened SecureChannel %i on Connection %i",
response->securityToken.channelId, connection->sockfd);
else
UA_LOG_DEBUG(server->config.logger, UA_LOGCATEGORY_SECURECHANNEL,
"Opening SecureChannel on Connection %i failed", connection->sockfd);
} else {
response->responseHeader.serviceResult =
UA_SecureChannelManager_renew(&server->secureChannelManager, connection, request, response);
if(response->responseHeader.serviceResult == UA_STATUSCODE_GOOD)
UA_LOG_DEBUG(server->config.logger, UA_LOGCATEGORY_SECURECHANNEL,
"Renewed SecureChannel %i on Connection %i",
response->securityToken.channelId, connection->sockfd);
else
UA_LOG_DEBUG(server->config.logger, UA_LOGCATEGORY_SECURECHANNEL,
"Renewing SecureChannel on Connection %i failed", connection->sockfd);
}
}
/* The server does not send a CloseSecureChannel response */
void Service_CloseSecureChannel(UA_Server *server, UA_UInt32 channelId) {
UA_LOG_DEBUG(server->config.logger, UA_LOGCATEGORY_SECURECHANNEL,
"Closing SecureChannel %i", channelId);
UA_SecureChannelManager_close(&server->secureChannelManager, channelId);
}
/*********************************** amalgamated original file "/home/wn/Sources/open62541-open62541-395ce48/src/server/ua_services_session.c" ***********************************/
void Service_CreateSession(UA_Server *server, UA_Session *session, const UA_CreateSessionRequest *request,
UA_CreateSessionResponse *response) {
UA_SecureChannel *channel = session->channel;
if(channel->securityToken.channelId == 0) {
response->responseHeader.serviceResult = UA_STATUSCODE_BADSECURECHANNELIDINVALID;
return;
}
response->responseHeader.serviceResult =
UA_Array_copy(server->endpointDescriptions, server->endpointDescriptionsSize,
(void**)&response->serverEndpoints, &UA_TYPES[UA_TYPES_ENDPOINTDESCRIPTION]);
if(response->responseHeader.serviceResult != UA_STATUSCODE_GOOD)
return;
response->serverEndpointsSize = server->endpointDescriptionsSize;
UA_Session *newSession;
response->responseHeader.serviceResult =
UA_SessionManager_createSession(&server->sessionManager, channel, request, &newSession);
if(response->responseHeader.serviceResult != UA_STATUSCODE_GOOD) {
UA_LOG_DEBUG(server->config.logger, UA_LOGCATEGORY_SESSION,
"Processing CreateSessionRequest on SecureChannel %i failed",
channel->securityToken.channelId);
return;
}
//TODO get maxResponseMessageSize internally
newSession->maxResponseMessageSize = request->maxResponseMessageSize;
response->sessionId = newSession->sessionId;
response->revisedSessionTimeout = (UA_Double)newSession->timeout;
response->authenticationToken = newSession->authenticationToken;
response->responseHeader.serviceResult = UA_String_copy(&request->sessionName, &newSession->sessionName);
if(server->endpointDescriptions)
response->responseHeader.serviceResult |=
UA_ByteString_copy(&server->endpointDescriptions->serverCertificate, &response->serverCertificate);
if(response->responseHeader.serviceResult != UA_STATUSCODE_GOOD) {
UA_SessionManager_removeSession(&server->sessionManager, &newSession->authenticationToken);
return;
}
UA_LOG_DEBUG(server->config.logger, UA_LOGCATEGORY_SESSION,
"Processing CreateSessionRequest on SecureChannel %i succeeded, created Session (ns=%i,i=%i)",
channel->securityToken.channelId, response->sessionId.namespaceIndex,
response->sessionId.identifier.numeric);
}
void
Service_ActivateSession(UA_Server *server, UA_Session *session, const UA_ActivateSessionRequest *request,
UA_ActivateSessionResponse *response) {
UA_SecureChannel *channel = session->channel;
// make the channel know about the session
UA_Session *foundSession =
UA_SessionManager_getSession(&server->sessionManager, &request->requestHeader.authenticationToken);
if(!foundSession) {
response->responseHeader.serviceResult = UA_STATUSCODE_BADSESSIONIDINVALID;
UA_LOG_DEBUG(server->config.logger, UA_LOGCATEGORY_SESSION,
"Processing ActivateSessionRequest on SecureChannel %i, "
"but no session found for the authentication token",
channel->securityToken.channelId);
return;
}
if(foundSession->validTill < UA_DateTime_now()) {
UA_LOG_DEBUG(server->config.logger, UA_LOGCATEGORY_SESSION,
"Processing ActivateSessionRequest on SecureChannel %i, but the session has timed out",
channel->securityToken.channelId);
response->responseHeader.serviceResult = UA_STATUSCODE_BADSESSIONIDINVALID;
return;
}
if(request->userIdentityToken.encoding < UA_EXTENSIONOBJECT_DECODED ||
(request->userIdentityToken.content.decoded.type != &UA_TYPES[UA_TYPES_ANONYMOUSIDENTITYTOKEN] &&
request->userIdentityToken.content.decoded.type != &UA_TYPES[UA_TYPES_USERNAMEIDENTITYTOKEN])) {
UA_LOG_DEBUG(server->config.logger, UA_LOGCATEGORY_SESSION,
"Invalided UserIdentityToken on SecureChannel %i for Session (ns=%i,i=%i)",
channel->securityToken.channelId, foundSession->sessionId.namespaceIndex,
foundSession->sessionId.identifier.numeric);
response->responseHeader.serviceResult = UA_STATUSCODE_BADINTERNALERROR;
return;
}
UA_LOG_DEBUG(server->config.logger, UA_LOGCATEGORY_SESSION,
"Processing ActivateSessionRequest on SecureChannel %i for Session (ns=%i,i=%i)",
channel->securityToken.channelId, foundSession->sessionId.namespaceIndex,
foundSession->sessionId.identifier.numeric);
UA_String ap = UA_STRING(ANONYMOUS_POLICY);
UA_String up = UA_STRING(USERNAME_POLICY);
/* Compatibility notice: Siemens OPC Scout v10 provides an empty policyId,
this is not okay For compatibility we will assume that empty policyId ==
ANONYMOUS_POLICY
if(token.policyId->data == NULL)
response->responseHeader.serviceResult = UA_STATUSCODE_BADIDENTITYTOKENINVALID;
*/
/* anonymous login */
if(server->config.enableAnonymousLogin &&
request->userIdentityToken.content.decoded.type == &UA_TYPES[UA_TYPES_ANONYMOUSIDENTITYTOKEN]) {
const UA_AnonymousIdentityToken *token = request->userIdentityToken.content.decoded.data;
if(token->policyId.data && !UA_String_equal(&token->policyId, &ap)) {
response->responseHeader.serviceResult = UA_STATUSCODE_BADIDENTITYTOKENINVALID;
return;
}
if(foundSession->channel && foundSession->channel != channel)
UA_SecureChannel_detachSession(foundSession->channel, foundSession);
UA_SecureChannel_attachSession(channel, foundSession);
foundSession->activated = true;
UA_Session_updateLifetime(foundSession);
return;
}
/* username login */
if(server->config.enableUsernamePasswordLogin &&
request->userIdentityToken.content.decoded.type == &UA_TYPES[UA_TYPES_USERNAMEIDENTITYTOKEN]) {
const UA_UserNameIdentityToken *token = request->userIdentityToken.content.decoded.data;
if(!UA_String_equal(&token->policyId, &up)) {
response->responseHeader.serviceResult = UA_STATUSCODE_BADIDENTITYTOKENINVALID;
return;
}
if(token->encryptionAlgorithm.length > 0) {
/* we don't support encryption */
response->responseHeader.serviceResult = UA_STATUSCODE_BADIDENTITYTOKENINVALID;
return;
}
/* ok, trying to match the username */
for(size_t i = 0; i < server->config.usernamePasswordLoginsSize; i++) {
UA_String *user = &server->config.usernamePasswordLogins[i].username;
UA_String *pw = &server->config.usernamePasswordLogins[i].password;
if(!UA_String_equal(&token->userName, user) || !UA_String_equal(&token->password, pw))
continue;
/* success - activate */
if(foundSession->channel && foundSession->channel != channel)
UA_SecureChannel_detachSession(foundSession->channel, foundSession);
UA_SecureChannel_attachSession(channel, foundSession);
foundSession->activated = true;
UA_Session_updateLifetime(foundSession);
return;
}
/* no match */
response->responseHeader.serviceResult = UA_STATUSCODE_BADUSERACCESSDENIED;
return;
}
response->responseHeader.serviceResult = UA_STATUSCODE_BADIDENTITYTOKENINVALID;
}
void
Service_CloseSession(UA_Server *server, UA_Session *session, const UA_CloseSessionRequest *request,
UA_CloseSessionResponse *response) {
UA_LOG_DEBUG(server->config.logger, UA_LOGCATEGORY_SESSION,
"Processing CloseSessionRequest for Session (ns=%i,i=%i)",
session->sessionId.namespaceIndex, session->sessionId.identifier.numeric);
response->responseHeader.serviceResult =
UA_SessionManager_removeSession(&server->sessionManager, &session->authenticationToken);
}
/*********************************** amalgamated original file "/home/wn/Sources/open62541-open62541-395ce48/src/server/ua_services_attribute.c" ***********************************/
/******************/
/* Read Attribute */
/******************/
static size_t
readNumber(UA_Byte *buf, size_t buflen, UA_UInt32 *number) {
UA_UInt32 n = 0;
size_t progress = 0;
/* read numbers until the end or a non-number character appears */
while(progress < buflen) {
UA_Byte c = buf[progress];
if('0' > c || '9' < c)
break;
n = (n*10) + (UA_UInt32)(c-'0');
progress++;
}
*number = n;
return progress;
}
static size_t
readDimension(UA_Byte *buf, size_t buflen, struct UA_NumericRangeDimension *dim) {
size_t progress = readNumber(buf, buflen, &dim->min);
if(progress == 0)
return 0;
if(buflen <= progress || buf[progress] != ':') {
dim->max = dim->min;
return progress;
}
progress++;
size_t progress2 = readNumber(&buf[progress], buflen - progress, &dim->max);
if(progress2 == 0)
return 0;
return progress + progress2;
}
#ifndef UA_BUILD_UNIT_TESTS
static
#endif
UA_StatusCode parse_numericrange(const UA_String *str, UA_NumericRange *range) {
size_t idx = 0;
size_t dimensionsMax = 0;
struct UA_NumericRangeDimension *dimensions = NULL;
UA_StatusCode retval = UA_STATUSCODE_GOOD;
size_t pos = 0;
do {
/* alloc dimensions */
if(idx >= dimensionsMax) {
struct UA_NumericRangeDimension *newds;
newds = UA_realloc(dimensions, sizeof(struct UA_NumericRangeDimension) * (dimensionsMax + 2));
if(!newds) {
retval = UA_STATUSCODE_BADOUTOFMEMORY;
break;
}
dimensions = newds;
dimensionsMax = dimensionsMax + 2;
}
/* read the dimension */
size_t progress = readDimension(&str->data[pos], str->length - pos, &dimensions[idx]);
if(progress == 0) {
retval = UA_STATUSCODE_BADINDEXRANGEINVALID;
break;
}
pos += progress;
idx++;
/* loop into the next dimension */
if(pos >= str->length)
break;
} while(str->data[pos] == ',' && pos++);
if(retval == UA_STATUSCODE_GOOD && idx > 0) {
range->dimensions = dimensions;
range->dimensionsSize = idx;
} else
UA_free(dimensions);
return retval;
}
#define CHECK_NODECLASS(CLASS) \
if(!(node->nodeClass & (CLASS))) { \
retval = UA_STATUSCODE_BADATTRIBUTEIDINVALID; \
break; \
}
static void handleServerTimestamps(UA_TimestampsToReturn timestamps, UA_DataValue* v) {
if(v && (timestamps == UA_TIMESTAMPSTORETURN_SERVER || timestamps == UA_TIMESTAMPSTORETURN_BOTH)) {
v->hasServerTimestamp = true;
v->serverTimestamp = UA_DateTime_now();
}
}
static void handleSourceTimestamps(UA_TimestampsToReturn timestamps, UA_DataValue* v) {
if(timestamps == UA_TIMESTAMPSTORETURN_SOURCE || timestamps == UA_TIMESTAMPSTORETURN_BOTH) {
v->hasSourceTimestamp = true;
v->sourceTimestamp = UA_DateTime_now();
}
}
/* force cast for zero-copy reading. ensure that the variant is never written into. */
static void forceVariantSetScalar(UA_Variant *v, const void *p, const UA_DataType *t) {
UA_Variant_init(v);
v->type = t;
v->data = (void*)(uintptr_t)p;
v->storageType = UA_VARIANT_DATA_NODELETE;
}
static UA_StatusCode getVariableNodeValue(const UA_VariableNode *vn, const UA_TimestampsToReturn timestamps,
const UA_ReadValueId *id, UA_DataValue *v) {
UA_NumericRange range;
UA_NumericRange *rangeptr = NULL;
UA_StatusCode retval = UA_STATUSCODE_GOOD;
if(id->indexRange.length > 0) {
retval = parse_numericrange(&id->indexRange, &range);
if(retval != UA_STATUSCODE_GOOD)
return retval;
rangeptr = &range;
}
if(vn->valueSource == UA_VALUESOURCE_VARIANT) {
if(vn->value.variant.callback.onRead)
vn->value.variant.callback.onRead(vn->value.variant.callback.handle, vn->nodeId,
&v->value, rangeptr);
if(!rangeptr) {
v->value = vn->value.variant.value;
v->value.storageType = UA_VARIANT_DATA_NODELETE;
} else
retval = UA_Variant_copyRange(&vn->value.variant.value, &v->value, range);
if(retval == UA_STATUSCODE_GOOD)
handleSourceTimestamps(timestamps, v);
} else {
if(vn->value.dataSource.read == NULL) {
retval = UA_STATUSCODE_BADINTERNALERROR;
} else {
UA_Boolean sourceTimeStamp = (timestamps == UA_TIMESTAMPSTORETURN_SOURCE ||
timestamps == UA_TIMESTAMPSTORETURN_BOTH);
retval = vn->value.dataSource.read(vn->value.dataSource.handle, vn->nodeId,
sourceTimeStamp, rangeptr, v);
}
}
if(rangeptr)
UA_free(range.dimensions);
return retval;
}
static UA_StatusCode getVariableNodeDataType(const UA_VariableNode *vn, UA_DataValue *v) {
UA_StatusCode retval = UA_STATUSCODE_GOOD;
if(vn->valueSource == UA_VALUESOURCE_VARIANT) {
forceVariantSetScalar(&v->value, &vn->value.variant.value.type->typeId,
&UA_TYPES[UA_TYPES_NODEID]);
} else {
if(vn->value.dataSource.read == NULL)
return UA_STATUSCODE_BADINTERNALERROR;
/* Read from the datasource to see the data type */
UA_DataValue val;
UA_DataValue_init(&val);
val.hasValue = false; // always assume we are not given a value by userspace
retval = vn->value.dataSource.read(vn->value.dataSource.handle, vn->nodeId, false, NULL, &val);
if(retval != UA_STATUSCODE_GOOD)
return retval;
if (val.hasValue && val.value.type != NULL)
retval = UA_Variant_setScalarCopy(&v->value, &val.value.type->typeId, &UA_TYPES[UA_TYPES_NODEID]);
UA_DataValue_deleteMembers(&val);
}
return retval;
}
static UA_StatusCode getVariableNodeArrayDimensions(const UA_VariableNode *vn, UA_DataValue *v) {
UA_StatusCode retval = UA_STATUSCODE_GOOD;
if(vn->valueSource == UA_VALUESOURCE_VARIANT) {
UA_Variant_setArray(&v->value, vn->value.variant.value.arrayDimensions,
vn->value.variant.value.arrayDimensionsSize, &UA_TYPES[UA_TYPES_INT32]);
v->value.storageType = UA_VARIANT_DATA_NODELETE;
} else {
if(vn->value.dataSource.read == NULL)
return UA_STATUSCODE_BADINTERNALERROR;
/* Read the datasource to see the array dimensions */
UA_DataValue val;
UA_DataValue_init(&val);
retval = vn->value.dataSource.read(vn->value.dataSource.handle, vn->nodeId, false, NULL, &val);
if(retval != UA_STATUSCODE_GOOD)
return retval;
retval = UA_Variant_setArrayCopy(&v->value, val.value.arrayDimensions,
val.value.arrayDimensionsSize, &UA_TYPES[UA_TYPES_INT32]);
UA_DataValue_deleteMembers(&val);
}
return retval;
}
static const UA_String binEncoding = {sizeof("DefaultBinary")-1, (UA_Byte*)"DefaultBinary"};
/* clang complains about unused variables */
// static const UA_String xmlEncoding = {sizeof("DefaultXml")-1, (UA_Byte*)"DefaultXml"};
/** Reads a single attribute from a node in the nodestore. */
void Service_Read_single(UA_Server *server, UA_Session *session, const UA_TimestampsToReturn timestamps,
const UA_ReadValueId *id, UA_DataValue *v) {
if(id->dataEncoding.name.length > 0 && !UA_String_equal(&binEncoding, &id->dataEncoding.name)) {
v->hasStatus = true;
v->status = UA_STATUSCODE_BADDATAENCODINGUNSUPPORTED;
return;
}
//index range for a non-value
if(id->indexRange.length > 0 && id->attributeId != UA_ATTRIBUTEID_VALUE){
v->hasStatus = true;
v->status = UA_STATUSCODE_BADINDEXRANGENODATA;
return;
}
UA_Node const *node = UA_NodeStore_get(server->nodestore, &id->nodeId);
if(!node) {
v->hasStatus = true;
v->status = UA_STATUSCODE_BADNODEIDUNKNOWN;
return;
}
/* When setting the value fails in the switch, we get an error code and set hasValue to false */
UA_StatusCode retval = UA_STATUSCODE_GOOD;
v->hasValue = true;
switch(id->attributeId) {
case UA_ATTRIBUTEID_NODEID:
forceVariantSetScalar(&v->value, &node->nodeId, &UA_TYPES[UA_TYPES_NODEID]);
break;
case UA_ATTRIBUTEID_NODECLASS:
forceVariantSetScalar(&v->value, &node->nodeClass, &UA_TYPES[UA_TYPES_NODECLASS]);
break;
case UA_ATTRIBUTEID_BROWSENAME:
forceVariantSetScalar(&v->value, &node->browseName, &UA_TYPES[UA_TYPES_QUALIFIEDNAME]);
break;
case UA_ATTRIBUTEID_DISPLAYNAME:
forceVariantSetScalar(&v->value, &node->displayName, &UA_TYPES[UA_TYPES_LOCALIZEDTEXT]);
break;
case UA_ATTRIBUTEID_DESCRIPTION:
forceVariantSetScalar(&v->value, &node->description, &UA_TYPES[UA_TYPES_LOCALIZEDTEXT]);
break;
case UA_ATTRIBUTEID_WRITEMASK:
forceVariantSetScalar(&v->value, &node->writeMask, &UA_TYPES[UA_TYPES_UINT32]);
break;
case UA_ATTRIBUTEID_USERWRITEMASK:
forceVariantSetScalar(&v->value, &node->userWriteMask, &UA_TYPES[UA_TYPES_UINT32]);
break;
case UA_ATTRIBUTEID_ISABSTRACT:
CHECK_NODECLASS(UA_NODECLASS_REFERENCETYPE | UA_NODECLASS_OBJECTTYPE |
UA_NODECLASS_VARIABLETYPE | UA_NODECLASS_DATATYPE);
forceVariantSetScalar(&v->value, &((const UA_ReferenceTypeNode*)node)->isAbstract,
&UA_TYPES[UA_TYPES_BOOLEAN]);
break;
case UA_ATTRIBUTEID_SYMMETRIC:
CHECK_NODECLASS(UA_NODECLASS_REFERENCETYPE);
forceVariantSetScalar(&v->value, &((const UA_ReferenceTypeNode*)node)->symmetric,
&UA_TYPES[UA_TYPES_BOOLEAN]);
break;
case UA_ATTRIBUTEID_INVERSENAME:
CHECK_NODECLASS(UA_NODECLASS_REFERENCETYPE);
forceVariantSetScalar(&v->value, &((const UA_ReferenceTypeNode*)node)->inverseName,
&UA_TYPES[UA_TYPES_LOCALIZEDTEXT]);
break;
case UA_ATTRIBUTEID_CONTAINSNOLOOPS:
CHECK_NODECLASS(UA_NODECLASS_VIEW);
forceVariantSetScalar(&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);
forceVariantSetScalar(&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);
retval = getVariableNodeValue((const UA_VariableNode*)node, timestamps, id, v);
break;
case UA_ATTRIBUTEID_DATATYPE:
CHECK_NODECLASS(UA_NODECLASS_VARIABLE | UA_NODECLASS_VARIABLETYPE);
retval = getVariableNodeDataType((const UA_VariableNode*)node, v);
break;
case UA_ATTRIBUTEID_VALUERANK:
CHECK_NODECLASS(UA_NODECLASS_VARIABLE | UA_NODECLASS_VARIABLETYPE);
forceVariantSetScalar(&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 = getVariableNodeArrayDimensions((const UA_VariableNode*)node, v);
break;
case UA_ATTRIBUTEID_ACCESSLEVEL:
CHECK_NODECLASS(UA_NODECLASS_VARIABLE);
forceVariantSetScalar(&v->value, &((const UA_VariableNode*)node)->accessLevel,
&UA_TYPES[UA_TYPES_BYTE]);
break;
case UA_ATTRIBUTEID_USERACCESSLEVEL:
CHECK_NODECLASS(UA_NODECLASS_VARIABLE);
forceVariantSetScalar(&v->value, &((const UA_VariableNode*)node)->userAccessLevel,
&UA_TYPES[UA_TYPES_BYTE]);
break;
case UA_ATTRIBUTEID_MINIMUMSAMPLINGINTERVAL:
CHECK_NODECLASS(UA_NODECLASS_VARIABLE);
forceVariantSetScalar(&v->value, &((const UA_VariableNode*)node)->minimumSamplingInterval,
&UA_TYPES[UA_TYPES_DOUBLE]);
break;
case UA_ATTRIBUTEID_HISTORIZING:
CHECK_NODECLASS(UA_NODECLASS_VARIABLE);
forceVariantSetScalar(&v->value, &((const UA_VariableNode*)node)->historizing,
&UA_TYPES[UA_TYPES_BOOLEAN]);
break;
case UA_ATTRIBUTEID_EXECUTABLE:
CHECK_NODECLASS(UA_NODECLASS_METHOD);
forceVariantSetScalar(&v->value, &((const UA_MethodNode*)node)->executable,
&UA_TYPES[UA_TYPES_BOOLEAN]);
break;
case UA_ATTRIBUTEID_USEREXECUTABLE:
CHECK_NODECLASS(UA_NODECLASS_METHOD);
forceVariantSetScalar(&v->value, &((const UA_MethodNode*)node)->userExecutable,
&UA_TYPES[UA_TYPES_BOOLEAN]);
break;
default:
retval = UA_STATUSCODE_BADATTRIBUTEIDINVALID;
break;
}
if(retval != UA_STATUSCODE_GOOD) {
v->hasValue = false;
v->hasStatus = true;
v->status = retval;
}
// Todo: what if the timestamp from the datasource are already present?
handleServerTimestamps(timestamps, v);
}
void Service_Read(UA_Server *server, UA_Session *session, const UA_ReadRequest *request,
UA_ReadResponse *response) {
UA_LOG_DEBUG(server->config.logger, UA_LOGCATEGORY_SESSION,
"Processing ReadRequest for Session (ns=%i,i=%i)",
session->sessionId.namespaceIndex, session->sessionId.identifier.numeric);
if(request->nodesToReadSize <= 0) {
response->responseHeader.serviceResult = UA_STATUSCODE_BADNOTHINGTODO;
return;
}
if(request->timestampsToReturn > 3){
response->responseHeader.serviceResult = UA_STATUSCODE_BADTIMESTAMPSTORETURNINVALID;
return;
}
size_t size = request->nodesToReadSize;
response->results = UA_Array_new(size, &UA_TYPES[UA_TYPES_DATAVALUE]);
if(!response->results) {
response->responseHeader.serviceResult = UA_STATUSCODE_BADOUTOFMEMORY;
return;
}
response->resultsSize = size;
if(request->maxAge < 0) {
response->responseHeader.serviceResult = UA_STATUSCODE_BADMAXAGEINVALID;
return;
}
#ifdef UA_ENABLE_EXTERNAL_NAMESPACES
UA_Boolean isExternal[size];
UA_UInt32 indices[size];
memset(isExternal, false, sizeof(UA_Boolean) * size);
for(size_t j = 0;j<server->externalNamespacesSize;j++) {
size_t indexSize = 0;
for(size_t i = 0;i < size;i++) {
if(request->nodesToRead[i].nodeId.namespaceIndex != server->externalNamespaces[j].index)
continue;
isExternal[i] = true;
indices[indexSize] = i;
indexSize++;
}
if(indexSize == 0)
continue;
UA_ExternalNodeStore *ens = &server->externalNamespaces[j].externalNodeStore;
ens->readNodes(ens->ensHandle, &request->requestHeader, request->nodesToRead,
indices, indexSize, response->results, false, response->diagnosticInfos);
}
#endif
for(size_t i = 0;i < size;i++) {
#ifdef UA_ENABLE_EXTERNAL_NAMESPACES
if(!isExternal[i])
#endif
Service_Read_single(server, session, request->timestampsToReturn,
&request->nodesToRead[i], &response->results[i]);
}
#ifdef UA_ENABLE_NONSTANDARD_STATELESS
/* Add an expiry header for caching */
if(session->sessionId.namespaceIndex == 0 &&
session->sessionId.identifierType == UA_NODEIDTYPE_NUMERIC &&
session->sessionId.identifier.numeric == 0){
UA_ExtensionObject additionalHeader;
UA_ExtensionObject_init(&additionalHeader);
additionalHeader.encoding = UA_EXTENSIONOBJECT_ENCODED_BYTESTRING;
additionalHeader.content.encoded.typeId =UA_TYPES[UA_TYPES_VARIANT].typeId;
UA_Variant variant;
UA_Variant_init(&variant);
UA_DateTime* expireArray = NULL;
expireArray = UA_Array_new(request->nodesToReadSize, &UA_TYPES[UA_TYPES_DATETIME]);
variant.data = expireArray;
/* expires in 20 seconds */
for(UA_UInt32 i = 0;i < response->resultsSize;i++) {
expireArray[i] = UA_DateTime_now() + 20 * 100 * 1000 * 1000;
}
UA_Variant_setArray(&variant, expireArray, request->nodesToReadSize, &UA_TYPES[UA_TYPES_DATETIME]);
size_t offset = 0;
UA_ByteString str;
UA_ByteString_allocBuffer(&str, UA_calcSizeBinary(&variant, &UA_TYPES[UA_TYPES_VARIANT]));
/* No chunking callback for the encoding */
UA_StatusCode retval = UA_encodeBinary(&variant, &UA_TYPES[UA_TYPES_VARIANT], NULL, NULL, &str, &offset);
UA_Array_delete(expireArray, request->nodesToReadSize, &UA_TYPES[UA_TYPES_DATETIME]);
if(retval == UA_STATUSCODE_GOOD){
additionalHeader.content.encoded.body.data = str.data;
additionalHeader.content.encoded.body.length = offset;
response->responseHeader.additionalHeader = additionalHeader;
}
}
#endif
}
/*******************/
/* Write Attribute */
/*******************/
UA_StatusCode UA_Server_editNode(UA_Server *server, UA_Session *session, const UA_NodeId *nodeId,
UA_EditNodeCallback callback, const void *data) {
UA_StatusCode retval;
do {
#ifndef UA_ENABLE_MULTITHREADING
const UA_Node *node = UA_NodeStore_get(server->nodestore, nodeId);
if(!node)
return UA_STATUSCODE_BADNODEIDUNKNOWN;
UA_Node *editNode = (UA_Node*)(uintptr_t)node; // dirty cast. use only here.
retval = callback(server, session, editNode, data);
return retval;
#else
UA_Node *copy = UA_NodeStore_getCopy(server->nodestore, nodeId);
if(!copy)
return UA_STATUSCODE_BADOUTOFMEMORY;
retval = callback(server, session, copy, data);
if(retval != UA_STATUSCODE_GOOD) {
UA_NodeStore_deleteNode(copy);
return retval;
}
retval = UA_NodeStore_replace(server->nodestore, copy);
#endif
} while(retval != UA_STATUSCODE_GOOD);
return UA_STATUSCODE_GOOD;
}
#define CHECK_DATATYPE(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; \
}
static UA_StatusCode
Service_Write_single_ValueDataSource(UA_Server *server, UA_Session *session, const UA_VariableNode *node,
const UA_WriteValue *wvalue) {
UA_assert(wvalue->attributeId == UA_ATTRIBUTEID_VALUE);
UA_assert(node->nodeClass == UA_NODECLASS_VARIABLE || node->nodeClass == UA_NODECLASS_VARIABLETYPE);
UA_assert(node->valueSource == UA_VALUESOURCE_DATASOURCE);
if(node->value.dataSource.write == NULL)
return UA_STATUSCODE_BADWRITENOTSUPPORTED;
UA_StatusCode retval;
if(wvalue->indexRange.length <= 0) {
retval = node->value.dataSource.write(node->value.dataSource.handle, node->nodeId,
&wvalue->value.value, NULL);
} else {
UA_NumericRange range;
retval = parse_numericrange(&wvalue->indexRange, &range);
if(retval != UA_STATUSCODE_GOOD)
return retval;
retval = node->value.dataSource.write(node->value.dataSource.handle, node->nodeId,
&wvalue->value.value, &range);
UA_free(range.dimensions);
}
return retval;
}
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;
}
static UA_StatusCode
CopyValueIntoNode(UA_VariableNode *node, const UA_WriteValue *wvalue) {
UA_assert(wvalue->attributeId == UA_ATTRIBUTEID_VALUE);
UA_assert(node->nodeClass == UA_NODECLASS_VARIABLE || node->nodeClass == UA_NODECLASS_VARIABLETYPE);
UA_assert(node->valueSource == UA_VALUESOURCE_VARIANT);
/* Parse the range */
UA_NumericRange range;
UA_NumericRange *rangeptr = NULL;
UA_StatusCode retval = UA_STATUSCODE_GOOD;
if(wvalue->indexRange.length > 0) {
retval = parse_numericrange(&wvalue->indexRange, &range);
if(retval != UA_STATUSCODE_GOOD)
return retval;
rangeptr = &range;
}
/* The nodeid on the wire may be != the nodeid in the node: opaque types, enums and bytestrings.
nodeV contains the correct type definition. */
const UA_Variant *newV = &wvalue->value.value;
UA_Variant *oldV = &node->value.variant.value;
UA_Variant cast_v;
if (oldV->type != NULL) { // Don't run NodeId_equal on a NULL pointer (happens if the variable never held a variant)
if(!UA_NodeId_equal(&oldV->type->typeId, &newV->type->typeId)) {
cast_v = wvalue->value.value;
newV = &cast_v;
enum type_equivalence te1 = typeEquivalence(oldV->type);
enum type_equivalence te2 = typeEquivalence(newV->type);
if(te1 != TYPE_EQUIVALENCE_NONE && te1 == te2) {
/* An enum was sent as an int32, or an opaque type as a bytestring. This is
detected with the typeIndex indicated the "true" datatype. */
cast_v.type = oldV->type;
} else if(oldV->type == &UA_TYPES[UA_TYPES_BYTE] && !UA_Variant_isScalar(oldV) &&
newV->type == &UA_TYPES[UA_TYPES_BYTESTRING] && UA_Variant_isScalar(newV)) {
/* a string is written to a byte array */
UA_ByteString *str = (UA_ByteString*) newV->data;
cast_v.arrayLength = str->length;
cast_v.data = str->data;
cast_v.type = &UA_TYPES[UA_TYPES_BYTE];
} else {
if(rangeptr)
UA_free(range.dimensions);
return UA_STATUSCODE_BADTYPEMISMATCH;
}
}
}
if(!rangeptr) {
UA_Variant_deleteMembers(&node->value.variant.value);
UA_Variant_copy(newV, &node->value.variant.value);
} else
retval = UA_Variant_setRangeCopy(&node->value.variant.value, newV->data, newV->arrayLength, range);
if(node->value.variant.callback.onWrite)
node->value.variant.callback.onWrite(node->value.variant.callback.handle, node->nodeId,
&node->value.variant.value, rangeptr);
if(rangeptr)
UA_free(range.dimensions);
return retval;
}
static UA_StatusCode
CopyAttributeIntoNode(UA_Server *server, UA_Session *session,
UA_Node *node, const UA_WriteValue *wvalue) {
if(!wvalue->value.hasValue)
return UA_STATUSCODE_BADNODATA;
void *value = wvalue->value.value.data;
void *target = NULL;
const UA_DataType *attr_type = NULL;
UA_StatusCode retval = UA_STATUSCODE_GOOD;
switch(wvalue->attributeId) {
case UA_ATTRIBUTEID_NODEID:
case UA_ATTRIBUTEID_NODECLASS:
case UA_ATTRIBUTEID_DATATYPE:
retval = UA_STATUSCODE_BADWRITENOTSUPPORTED;
break;
case UA_ATTRIBUTEID_BROWSENAME:
CHECK_DATATYPE(QUALIFIEDNAME);
target = &node->browseName;
attr_type = &UA_TYPES[UA_TYPES_QUALIFIEDNAME];
break;
case UA_ATTRIBUTEID_DISPLAYNAME:
CHECK_DATATYPE(LOCALIZEDTEXT);
target = &node->displayName;
attr_type = &UA_TYPES[UA_TYPES_LOCALIZEDTEXT];
break;
case UA_ATTRIBUTEID_DESCRIPTION:
CHECK_DATATYPE(LOCALIZEDTEXT);
target = &node->description;
attr_type = &UA_TYPES[UA_TYPES_LOCALIZEDTEXT];
break;
case UA_ATTRIBUTEID_WRITEMASK:
CHECK_DATATYPE(UINT32);
node->writeMask = *(UA_UInt32*)value;
break;
case UA_ATTRIBUTEID_USERWRITEMASK:
CHECK_DATATYPE(UINT32);
node->userWriteMask = *(UA_UInt32*)value;
break;
case UA_ATTRIBUTEID_ISABSTRACT:
CHECK_NODECLASS_WRITE(UA_NODECLASS_OBJECTTYPE | UA_NODECLASS_REFERENCETYPE |
UA_NODECLASS_VARIABLETYPE | UA_NODECLASS_DATATYPE);
CHECK_DATATYPE(BOOLEAN);
((UA_ObjectTypeNode*)node)->isAbstract = *(UA_Boolean*)value;
break;
case UA_ATTRIBUTEID_SYMMETRIC:
CHECK_NODECLASS_WRITE(UA_NODECLASS_REFERENCETYPE);
CHECK_DATATYPE(BOOLEAN);
((UA_ReferenceTypeNode*)node)->symmetric = *(UA_Boolean*)value;
break;
case UA_ATTRIBUTEID_INVERSENAME:
CHECK_NODECLASS_WRITE(UA_NODECLASS_REFERENCETYPE);
CHECK_DATATYPE(LOCALIZEDTEXT);
target = &((UA_ReferenceTypeNode*)node)->inverseName;
attr_type = &UA_TYPES[UA_TYPES_LOCALIZEDTEXT];
break;
case UA_ATTRIBUTEID_CONTAINSNOLOOPS:
CHECK_NODECLASS_WRITE(UA_NODECLASS_VIEW);
CHECK_DATATYPE(BOOLEAN);
((UA_ViewNode*)node)->containsNoLoops = *(UA_Boolean*)value;
break;
case UA_ATTRIBUTEID_EVENTNOTIFIER:
CHECK_NODECLASS_WRITE(UA_NODECLASS_VIEW | UA_NODECLASS_OBJECT);
CHECK_DATATYPE(BYTE);
((UA_ViewNode*)node)->eventNotifier = *(UA_Byte*)value;
break;
case UA_ATTRIBUTEID_VALUE:
CHECK_NODECLASS_WRITE(UA_NODECLASS_VARIABLE | UA_NODECLASS_VARIABLETYPE);
if(((const UA_VariableNode*)node)->valueSource == UA_VALUESOURCE_VARIANT)
retval = CopyValueIntoNode((UA_VariableNode*)node, wvalue);
else
retval = Service_Write_single_ValueDataSource(server, session, (const UA_VariableNode*)node, wvalue);
break;
case UA_ATTRIBUTEID_ACCESSLEVEL:
CHECK_NODECLASS_WRITE(UA_NODECLASS_VARIABLE);
CHECK_DATATYPE(BYTE);
((UA_VariableNode*)node)->accessLevel = *(UA_Byte*)value;
break;
case UA_ATTRIBUTEID_USERACCESSLEVEL:
CHECK_NODECLASS_WRITE(UA_NODECLASS_VARIABLE);
CHECK_DATATYPE(BYTE);
((UA_VariableNode*)node)->userAccessLevel = *(UA_Byte*)value;
break;
case UA_ATTRIBUTEID_MINIMUMSAMPLINGINTERVAL:
CHECK_NODECLASS_WRITE(UA_NODECLASS_VARIABLE);
CHECK_DATATYPE(DOUBLE);
((UA_VariableNode*)node)->minimumSamplingInterval = *(UA_Double*)value;
break;
case UA_ATTRIBUTEID_HISTORIZING:
CHECK_NODECLASS_WRITE(UA_NODECLASS_VARIABLE);
CHECK_DATATYPE(BOOLEAN);
((UA_VariableNode*)node)->historizing = *(UA_Boolean*)value;
break;
case UA_ATTRIBUTEID_EXECUTABLE:
CHECK_NODECLASS_WRITE(UA_NODECLASS_METHOD);
CHECK_DATATYPE(BOOLEAN);
((UA_MethodNode*)node)->executable = *(UA_Boolean*)value;
break;
case UA_ATTRIBUTEID_USEREXECUTABLE:
CHECK_NODECLASS_WRITE(UA_NODECLASS_METHOD);
CHECK_DATATYPE(BOOLEAN);
((UA_MethodNode*)node)->userExecutable = *(UA_Boolean*)value;
break;
default:
retval = UA_STATUSCODE_BADATTRIBUTEIDINVALID;
break;
}
if(attr_type) {
UA_deleteMembers(target, attr_type);
retval = UA_copy(value, target, attr_type);
}
return retval;
}
UA_StatusCode Service_Write_single(UA_Server *server, UA_Session *session, const UA_WriteValue *wvalue) {
return UA_Server_editNode(server, session, &wvalue->nodeId, (UA_EditNodeCallback)CopyAttributeIntoNode, wvalue);
}
void Service_Write(UA_Server *server, UA_Session *session, const UA_WriteRequest *request,
UA_WriteResponse *response) {
UA_assert(server != NULL && session != NULL && request != NULL && response != NULL);
UA_LOG_DEBUG(server->config.logger, UA_LOGCATEGORY_SESSION,
"Processing WriteRequest for Session (ns=%i,i=%i)",
session->sessionId.namespaceIndex, session->sessionId.identifier.numeric);
if(request->nodesToWriteSize <= 0) {
response->responseHeader.serviceResult = UA_STATUSCODE_BADNOTHINGTODO;
return;
}
response->results = UA_Array_new(request->nodesToWriteSize, &UA_TYPES[UA_TYPES_STATUSCODE]);
if(!response->results) {
response->responseHeader.serviceResult = UA_STATUSCODE_BADOUTOFMEMORY;
return;
}
#ifdef UA_ENABLE_EXTERNAL_NAMESPACES
UA_Boolean isExternal[request->nodesToWriteSize];
UA_UInt32 indices[request->nodesToWriteSize];
memset(isExternal, false, sizeof(UA_Boolean)*request->nodesToWriteSize);
for(size_t j = 0; j < server->externalNamespacesSize; j++) {
UA_UInt32 indexSize = 0;
for(size_t i = 0; i < request->nodesToWriteSize; i++) {
if(request->nodesToWrite[i].nodeId.namespaceIndex !=
server->externalNamespaces[j].index)
continue;
isExternal[i] = true;
indices[indexSize] = i;
indexSize++;
}
if(indexSize == 0)
continue;
UA_ExternalNodeStore *ens = &server->externalNamespaces[j].externalNodeStore;
ens->writeNodes(ens->ensHandle, &request->requestHeader, request->nodesToWrite,
indices, indexSize, response->results, response->diagnosticInfos);
}
#endif
response->resultsSize = request->nodesToWriteSize;
for(size_t i = 0;i < request->nodesToWriteSize;i++) {
#ifdef UA_ENABLE_EXTERNAL_NAMESPACES
if(!isExternal[i])
#endif
response->results[i] = Service_Write_single(server, session, &request->nodesToWrite[i]);
}
}
/*********************************** amalgamated original file "/home/wn/Sources/open62541-open62541-395ce48/src/server/ua_services_nodemanagement.c" ***********************************/
/************/
/* Add Node */
/************/
void
Service_AddNodes_existing(UA_Server *server, UA_Session *session, UA_Node *node,
const UA_NodeId *parentNodeId, const UA_NodeId *referenceTypeId,
UA_AddNodesResult *result) {
if(node->nodeId.namespaceIndex >= server->namespacesSize) {
result->statusCode = UA_STATUSCODE_BADNODEIDINVALID;
UA_NodeStore_deleteNode(node);
return;
}
const UA_Node *parent = UA_NodeStore_get(server->nodestore, parentNodeId);
if(!parent) {
result->statusCode = UA_STATUSCODE_BADPARENTNODEIDINVALID;
UA_NodeStore_deleteNode(node);
return;
}
const UA_ReferenceTypeNode *referenceType =
(const UA_ReferenceTypeNode *)UA_NodeStore_get(server->nodestore, referenceTypeId);
if(!referenceType) {
result->statusCode = UA_STATUSCODE_BADREFERENCETYPEIDINVALID;
UA_NodeStore_deleteNode(node);
return;
}
if(referenceType->nodeClass != UA_NODECLASS_REFERENCETYPE) {
result->statusCode = UA_STATUSCODE_BADREFERENCETYPEIDINVALID;
UA_NodeStore_deleteNode(node);
return;
}
if(referenceType->isAbstract == true) {
result->statusCode = UA_STATUSCODE_BADREFERENCENOTALLOWED;
UA_NodeStore_deleteNode(node);
return;
}
// todo: test if the referencetype is hierarchical
// todo: namespace index is assumed to be valid
result->statusCode = UA_NodeStore_insert(server->nodestore, node);
if(result->statusCode == UA_STATUSCODE_GOOD)
result->statusCode = UA_NodeId_copy(&node->nodeId, &result->addedNodeId);
else
return;
// reference back to the parent
UA_AddReferencesItem item;
UA_AddReferencesItem_init(&item);
item.sourceNodeId = node->nodeId;
item.referenceTypeId = *referenceTypeId;
item.isForward = false;
item.targetNodeId.nodeId = *parentNodeId;
Service_AddReferences_single(server, session, &item);
// todo: error handling. remove new node from nodestore
}
static UA_StatusCode
instantiateVariableNode(UA_Server *server, UA_Session *session,
const UA_NodeId *nodeId, const UA_NodeId *typeId,
UA_InstantiationCallback *instantiationCallback);
static UA_StatusCode
instantiateObjectNode(UA_Server *server, UA_Session *session,
const UA_NodeId *nodeId, const UA_NodeId *typeId,
UA_InstantiationCallback *instantiationCallback);
/* copy an existing variable under the given parent. then instantiate the
variable for all hastypedefinitions of the original version. */
static UA_StatusCode
copyExistingVariable(UA_Server *server, UA_Session *session, const UA_NodeId *variable,
const UA_NodeId *referenceType, const UA_NodeId *parent,
UA_InstantiationCallback *instantiationCallback) {
const UA_VariableNode *node = (const UA_VariableNode*)UA_NodeStore_get(server->nodestore, variable);
if(!node)
return UA_STATUSCODE_BADNODEIDINVALID;
if(node->nodeClass != UA_NODECLASS_VARIABLE)
return UA_STATUSCODE_BADNODECLASSINVALID;
// copy the variable attributes
UA_VariableAttributes attr;
UA_VariableAttributes_init(&attr);
UA_LocalizedText_copy(&node->displayName, &attr.displayName);
UA_LocalizedText_copy(&node->description, &attr.description);
attr.writeMask = node->writeMask;
attr.userWriteMask = node->userWriteMask;
// todo: handle data sources!!!!
UA_Variant_copy(&node->value.variant.value, &attr.value);
// datatype is taken from the value
// valuerank is taken from the value
// array dimensions are taken from the value
attr.accessLevel = node->accessLevel;
attr.userAccessLevel = node->userAccessLevel;
attr.minimumSamplingInterval = node->minimumSamplingInterval;
attr.historizing = node->historizing;
UA_AddNodesItem item;
UA_AddNodesItem_init(&item);
UA_NodeId_copy(parent, &item.parentNodeId.nodeId);
UA_NodeId_copy(referenceType, &item.referenceTypeId);
UA_QualifiedName_copy(&node->browseName, &item.browseName);
item.nodeClass = UA_NODECLASS_VARIABLE;
item.nodeAttributes.encoding = UA_EXTENSIONOBJECT_DECODED_NODELETE;
item.nodeAttributes.content.decoded.type = &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES];
item.nodeAttributes.content.decoded.data = &attr;
// don't add a typedefinition here.
// add the new variable
UA_AddNodesResult res;
UA_AddNodesResult_init(&res);
Service_AddNodes_single(server, session, &item, &res, instantiationCallback);
UA_VariableAttributes_deleteMembers(&attr);
UA_AddNodesItem_deleteMembers(&item);
// now instantiate the variable for all hastypedefinition references
for(size_t i = 0; i < node->referencesSize; i++) {
UA_ReferenceNode *rn = &node->references[i];
if(rn->isInverse)
continue;
const UA_NodeId hasTypeDef = UA_NODEID_NUMERIC(0, UA_NS0ID_HASTYPEDEFINITION);
if(!UA_NodeId_equal(&rn->referenceTypeId, &hasTypeDef))
continue;
instantiateVariableNode(server, session, &res.addedNodeId, &rn->targetId.nodeId, instantiationCallback);
}
if (instantiationCallback != NULL)
instantiationCallback->method(res.addedNodeId, node->nodeId, instantiationCallback->handle);
UA_AddNodesResult_deleteMembers(&res);
return UA_STATUSCODE_GOOD;
}
/* copy an existing object under the given parent. then instantiate the
variable for all hastypedefinitions of the original version. */
static UA_StatusCode
copyExistingObject(UA_Server *server, UA_Session *session, const UA_NodeId *variable,
const UA_NodeId *referenceType, const UA_NodeId *parent,
UA_InstantiationCallback *instantiationCallback) {
const UA_ObjectNode *node = (const UA_ObjectNode*)UA_NodeStore_get(server->nodestore, variable);
if(!node)
return UA_STATUSCODE_BADNODEIDINVALID;
if(node->nodeClass != UA_NODECLASS_OBJECT)
return UA_STATUSCODE_BADNODECLASSINVALID;
// copy the variable attributes
UA_ObjectAttributes attr;
UA_ObjectAttributes_init(&attr);
UA_LocalizedText_copy(&node->displayName, &attr.displayName);
UA_LocalizedText_copy(&node->description, &attr.description);
attr.writeMask = node->writeMask;
attr.userWriteMask = node->userWriteMask;
attr.eventNotifier = node->eventNotifier;
UA_AddNodesItem item;
UA_AddNodesItem_init(&item);
UA_NodeId_copy(parent, &item.parentNodeId.nodeId);
UA_NodeId_copy(referenceType, &item.referenceTypeId);
UA_QualifiedName_copy(&node->browseName, &item.browseName);
item.nodeClass = UA_NODECLASS_OBJECT;
item.nodeAttributes.encoding = UA_EXTENSIONOBJECT_DECODED_NODELETE;
item.nodeAttributes.content.decoded.type = &UA_TYPES[UA_TYPES_OBJECTATTRIBUTES];
item.nodeAttributes.content.decoded.data = &attr;
// don't add a typedefinition here.
// add the new object
UA_AddNodesResult res;
UA_AddNodesResult_init(&res);
Service_AddNodes_single(server, session, &item, &res, instantiationCallback);
UA_ObjectAttributes_deleteMembers(&attr);
UA_AddNodesItem_deleteMembers(&item);
// now instantiate the object for all hastypedefinition references
for(size_t i = 0; i < node->referencesSize; i++) {
UA_ReferenceNode *rn = &node->references[i];
if(rn->isInverse)
continue;
const UA_NodeId hasTypeDef = UA_NODEID_NUMERIC(0, UA_NS0ID_HASTYPEDEFINITION);
if(!UA_NodeId_equal(&rn->referenceTypeId, &hasTypeDef))
continue;
instantiateObjectNode(server, session, &res.addedNodeId, &rn->targetId.nodeId, instantiationCallback);
}
if (instantiationCallback != NULL)
instantiationCallback->method(res.addedNodeId, node->nodeId, instantiationCallback->handle);
UA_AddNodesResult_deleteMembers(&res);
return UA_STATUSCODE_GOOD;
}
static UA_StatusCode
setObjectInstanceHandle(UA_Server *server, UA_Session *session, UA_ObjectNode* node, void *handle) {
if(node->nodeClass != UA_NODECLASS_OBJECT)
return UA_STATUSCODE_BADNODECLASSINVALID;
node->instanceHandle = handle;
return UA_STATUSCODE_GOOD;
}
static UA_StatusCode
instantiateObjectNode(UA_Server *server, UA_Session *session,
const UA_NodeId *nodeId, const UA_NodeId *typeId,
UA_InstantiationCallback *instantiationCallback) {
const UA_ObjectTypeNode *typenode = (const UA_ObjectTypeNode*)UA_NodeStore_get(server->nodestore, typeId);
if(!typenode)
return UA_STATUSCODE_BADNODEIDINVALID;
if(typenode->nodeClass != UA_NODECLASS_OBJECTTYPE)
return UA_STATUSCODE_BADNODECLASSINVALID;
/* Add all the child nodes */
UA_BrowseDescription browseChildren;
UA_BrowseDescription_init(&browseChildren);
browseChildren.nodeId = *typeId;
browseChildren.referenceTypeId = UA_NODEID_NUMERIC(0, UA_NS0ID_AGGREGATES);
browseChildren.includeSubtypes = true;
browseChildren.browseDirection = UA_BROWSEDIRECTION_FORWARD;
browseChildren.nodeClassMask = UA_NODECLASS_OBJECT | UA_NODECLASS_VARIABLE | UA_NODECLASS_METHOD;
browseChildren.resultMask = UA_BROWSERESULTMASK_REFERENCETYPEID | UA_BROWSERESULTMASK_NODECLASS;
UA_BrowseResult browseResult;
UA_BrowseResult_init(&browseResult);
// todo: continuation points if there are too many results
Service_Browse_single(server, session, NULL, &browseChildren, 100, &browseResult);
for(size_t i = 0; i < browseResult.referencesSize; i++) {
UA_ReferenceDescription *rd = &browseResult.references[i];
if(rd->nodeClass == UA_NODECLASS_METHOD) {
/* add a reference to the method in the objecttype */
UA_AddReferencesItem item;
UA_AddReferencesItem_init(&item);
item.sourceNodeId = *nodeId;
item.referenceTypeId = rd->referenceTypeId;
item.isForward = true;
item.targetNodeId = rd->nodeId;
item.targetNodeClass = UA_NODECLASS_METHOD;
Service_AddReferences_single(server, session, &item);
} else if(rd->nodeClass == UA_NODECLASS_VARIABLE)
copyExistingVariable(server, session, &rd->nodeId.nodeId,
&rd->referenceTypeId, nodeId, instantiationCallback);
else if(rd->nodeClass == UA_NODECLASS_OBJECT)
copyExistingObject(server, session, &rd->nodeId.nodeId,
&rd->referenceTypeId, nodeId, instantiationCallback);
}
/* add a hastypedefinition reference */
UA_AddReferencesItem addref;
UA_AddReferencesItem_init(&addref);
addref.sourceNodeId = *nodeId;
addref.referenceTypeId = UA_NODEID_NUMERIC(0, UA_NS0ID_HASTYPEDEFINITION);
addref.isForward = true;
addref.targetNodeId.nodeId = *typeId;
addref.targetNodeClass = UA_NODECLASS_OBJECTTYPE;
Service_AddReferences_single(server, session, &addref);
/* call the constructor */
const UA_ObjectLifecycleManagement *olm = &typenode->lifecycleManagement;
if(olm->constructor)
UA_Server_editNode(server, session, nodeId,
(UA_EditNodeCallback)setObjectInstanceHandle, olm->constructor(*nodeId));
return UA_STATUSCODE_GOOD;
}
static UA_StatusCode
instantiateVariableNode(UA_Server *server, UA_Session *session, const UA_NodeId *nodeId,
const UA_NodeId *typeId, UA_InstantiationCallback *instantiationCallback) {
const UA_ObjectTypeNode *typenode = (const UA_ObjectTypeNode*)UA_NodeStore_get(server->nodestore, typeId);
if(!typenode)
return UA_STATUSCODE_BADNODEIDINVALID;
if(typenode->nodeClass != UA_NODECLASS_VARIABLETYPE)
return UA_STATUSCODE_BADNODECLASSINVALID;
/* get the references to child properties */
UA_BrowseDescription browseChildren;
UA_BrowseDescription_init(&browseChildren);
browseChildren.nodeId = *typeId;
browseChildren.referenceTypeId = UA_NODEID_NUMERIC(0, UA_NS0ID_HASPROPERTY);
browseChildren.includeSubtypes = true;
browseChildren.browseDirection = UA_BROWSEDIRECTION_FORWARD;
browseChildren.nodeClassMask = UA_NODECLASS_VARIABLE;
browseChildren.resultMask = UA_BROWSERESULTMASK_REFERENCETYPEID | UA_BROWSERESULTMASK_NODECLASS;
UA_BrowseResult browseResult;
UA_BrowseResult_init(&browseResult);
// todo: continuation points if there are too many results
Service_Browse_single(server, session, NULL, &browseChildren, 100, &browseResult);
/* add the child properties */
for(size_t i = 0; i < browseResult.referencesSize; i++) {
UA_ReferenceDescription *rd = &browseResult.references[i];
copyExistingVariable(server, session, &rd->nodeId.nodeId,
&rd->referenceTypeId, nodeId, instantiationCallback);
}
/* add a hastypedefinition reference */
UA_AddReferencesItem addref;
UA_AddReferencesItem_init(&addref);
addref.sourceNodeId = *nodeId;
addref.referenceTypeId = UA_NODEID_NUMERIC(0, UA_NS0ID_HASTYPEDEFINITION);
addref.isForward = true;
addref.targetNodeId.nodeId = *typeId;
addref.targetNodeClass = UA_NODECLASS_OBJECTTYPE;
Service_AddReferences_single(server, session, &addref);
return UA_STATUSCODE_GOOD;
}
static UA_StatusCode
copyStandardAttributes(UA_Node *node, const UA_AddNodesItem *item, const UA_NodeAttributes *attr) {
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_LocalizedText_copy(&attr->displayName, &node->displayName);
retval |= UA_LocalizedText_copy(&attr->description, &node->description);
node->writeMask = attr->writeMask;
node->userWriteMask = attr->userWriteMask;
return retval;
}
static UA_Node *
variableNodeFromAttributes(const UA_AddNodesItem *item, const UA_VariableAttributes *attr) {
UA_VariableNode *vnode = UA_NodeStore_newVariableNode();
if(!vnode)
return NULL;
UA_StatusCode retval = copyStandardAttributes((UA_Node*)vnode, item, (const UA_NodeAttributes*)attr);
// todo: test if the type / valueRank / value attributes are consistent
vnode->accessLevel = attr->accessLevel;
vnode->userAccessLevel = attr->userAccessLevel;
vnode->historizing = attr->historizing;
vnode->minimumSamplingInterval = attr->minimumSamplingInterval;
vnode->valueRank = attr->valueRank;
retval |= UA_Variant_copy(&attr->value, &vnode->value.variant.value);
if(retval != UA_STATUSCODE_GOOD) {
UA_NodeStore_deleteNode((UA_Node*)vnode);
return NULL;
}
return (UA_Node*)vnode;
}
static UA_Node *
objectNodeFromAttributes(const UA_AddNodesItem *item, const UA_ObjectAttributes *attr) {
UA_ObjectNode *onode = UA_NodeStore_newObjectNode();
if(!onode)
return NULL;
UA_StatusCode retval = copyStandardAttributes((UA_Node*)onode, item, (const UA_NodeAttributes*)attr);
onode->eventNotifier = attr->eventNotifier;
if(retval != UA_STATUSCODE_GOOD) {
UA_NodeStore_deleteNode((UA_Node*)onode);
return NULL;
}
return (UA_Node*)onode;
}
static UA_Node *
referenceTypeNodeFromAttributes(const UA_AddNodesItem *item, const UA_ReferenceTypeAttributes *attr) {
UA_ReferenceTypeNode *rtnode = UA_NodeStore_newReferenceTypeNode();
if(!rtnode)
return NULL;
UA_StatusCode retval = copyStandardAttributes((UA_Node*)rtnode, item, (const UA_NodeAttributes*)attr);
rtnode->isAbstract = attr->isAbstract;
rtnode->symmetric = attr->symmetric;
retval |= UA_LocalizedText_copy(&attr->inverseName, &rtnode->inverseName);
if(retval != UA_STATUSCODE_GOOD) {
UA_NodeStore_deleteNode((UA_Node*)rtnode);
return NULL;
}
return (UA_Node*)rtnode;
}
static UA_Node *
objectTypeNodeFromAttributes(const UA_AddNodesItem *item, const UA_ObjectTypeAttributes *attr) {
UA_ObjectTypeNode *otnode = UA_NodeStore_newObjectTypeNode();
if(!otnode)
return NULL;
UA_StatusCode retval = copyStandardAttributes((UA_Node*)otnode, item, (const UA_NodeAttributes*)attr);
otnode->isAbstract = attr->isAbstract;
if(retval != UA_STATUSCODE_GOOD) {
UA_NodeStore_deleteNode((UA_Node*)otnode);
return NULL;
}
return (UA_Node*)otnode;
}
static UA_Node *
variableTypeNodeFromAttributes(const UA_AddNodesItem *item, const UA_VariableTypeAttributes *attr) {
UA_VariableTypeNode *vtnode = UA_NodeStore_newVariableTypeNode();
if(!vtnode)
return NULL;
UA_StatusCode retval = copyStandardAttributes((UA_Node*)vtnode, item, (const UA_NodeAttributes*)attr);
UA_Variant_copy(&attr->value, &vtnode->value.variant.value);
// datatype is taken from the value
vtnode->valueRank = attr->valueRank;
// array dimensions are taken from the value
vtnode->isAbstract = attr->isAbstract;
if(retval != UA_STATUSCODE_GOOD) {
UA_NodeStore_deleteNode((UA_Node*)vtnode);
return NULL;
}
return (UA_Node*)vtnode;
}
static UA_Node *
viewNodeFromAttributes(const UA_AddNodesItem *item, const UA_ViewAttributes *attr) {
UA_ViewNode *vnode = UA_NodeStore_newViewNode();
if(!vnode)
return NULL;
UA_StatusCode retval = copyStandardAttributes((UA_Node*)vnode, item, (const UA_NodeAttributes*)attr);
vnode->containsNoLoops = attr->containsNoLoops;
vnode->eventNotifier = attr->eventNotifier;
if(retval != UA_STATUSCODE_GOOD) {
UA_NodeStore_deleteNode((UA_Node*)vnode);
return NULL;
}
return (UA_Node*)vnode;
}
static UA_Node *
dataTypeNodeFromAttributes(const UA_AddNodesItem *item, const UA_DataTypeAttributes *attr) {
UA_DataTypeNode *dtnode = UA_NodeStore_newDataTypeNode();
if(!dtnode)
return NULL;
UA_StatusCode retval = copyStandardAttributes((UA_Node*)dtnode, item, (const UA_NodeAttributes*)attr);
dtnode->isAbstract = attr->isAbstract;
if(retval != UA_STATUSCODE_GOOD) {
UA_NodeStore_deleteNode((UA_Node*)dtnode);
return NULL;
}
return (UA_Node*)dtnode;
}
void Service_AddNodes_single(UA_Server *server, UA_Session *session, const UA_AddNodesItem *item,
UA_AddNodesResult *result, UA_InstantiationCallback *instantiationCallback) {
if(item->nodeAttributes.encoding < UA_EXTENSIONOBJECT_DECODED ||
!item->nodeAttributes.content.decoded.type) {
result->statusCode = UA_STATUSCODE_BADNODEATTRIBUTESINVALID;
return;
}
/* create the node */
UA_Node *node;
switch(item->nodeClass) {
case UA_NODECLASS_OBJECT:
if(item->nodeAttributes.content.decoded.type != &UA_TYPES[UA_TYPES_OBJECTATTRIBUTES]) {
result->statusCode = UA_STATUSCODE_BADNODEATTRIBUTESINVALID;
return;
}
node = objectNodeFromAttributes(item, item->nodeAttributes.content.decoded.data);
break;
case UA_NODECLASS_VARIABLE:
if(item->nodeAttributes.content.decoded.type != &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES]) {
result->statusCode = UA_STATUSCODE_BADNODEATTRIBUTESINVALID;
return;
}
node = variableNodeFromAttributes(item, item->nodeAttributes.content.decoded.data);
break;
case UA_NODECLASS_OBJECTTYPE:
if(item->nodeAttributes.content.decoded.type != &UA_TYPES[UA_TYPES_OBJECTTYPEATTRIBUTES]) {
result->statusCode = UA_STATUSCODE_BADNODEATTRIBUTESINVALID;
return;
}
node = objectTypeNodeFromAttributes(item, item->nodeAttributes.content.decoded.data);
break;
case UA_NODECLASS_VARIABLETYPE:
if(item->nodeAttributes.content.decoded.type != &UA_TYPES[UA_TYPES_VARIABLETYPEATTRIBUTES]) {
result->statusCode = UA_STATUSCODE_BADNODEATTRIBUTESINVALID;
return;
}
node = variableTypeNodeFromAttributes(item, item->nodeAttributes.content.decoded.data);
break;
case UA_NODECLASS_REFERENCETYPE:
if(item->nodeAttributes.content.decoded.type != &UA_TYPES[UA_TYPES_REFERENCETYPEATTRIBUTES]) {
result->statusCode = UA_STATUSCODE_BADNODEATTRIBUTESINVALID;
return;
}
node = referenceTypeNodeFromAttributes(item, item->nodeAttributes.content.decoded.data);
break;
case UA_NODECLASS_DATATYPE:
if(item->nodeAttributes.content.decoded.type != &UA_TYPES[UA_TYPES_DATATYPEATTRIBUTES]) {
result->statusCode = UA_STATUSCODE_BADNODEATTRIBUTESINVALID;
return;
}
node = dataTypeNodeFromAttributes(item, item->nodeAttributes.content.decoded.data);
break;
case UA_NODECLASS_VIEW:
if(item->nodeAttributes.content.decoded.type != &UA_TYPES[UA_TYPES_VIEWATTRIBUTES]) {
result->statusCode = UA_STATUSCODE_BADNODEATTRIBUTESINVALID;
return;
}
node = viewNodeFromAttributes(item, item->nodeAttributes.content.decoded.data);
break;
case UA_NODECLASS_METHOD:
case UA_NODECLASS_UNSPECIFIED:
default:
result->statusCode = UA_STATUSCODE_BADNODECLASSINVALID;
return;
}
if(!node) {
result->statusCode = UA_STATUSCODE_BADOUTOFMEMORY;
return;
}
/* add it to the server */
Service_AddNodes_existing(server, session, node, &item->parentNodeId.nodeId,
&item->referenceTypeId, result);
if(result->statusCode != UA_STATUSCODE_GOOD)
return;
/* instantiate if it has a type */
if(!UA_NodeId_isNull(&item->typeDefinition.nodeId)) {
if (instantiationCallback != NULL)
instantiationCallback->method(result->addedNodeId, item->typeDefinition.nodeId,
instantiationCallback->handle);
if(item->nodeClass == UA_NODECLASS_OBJECT)
result->statusCode = instantiateObjectNode(server, session, &result->addedNodeId,
&item->typeDefinition.nodeId, instantiationCallback);
else if(item->nodeClass == UA_NODECLASS_VARIABLE)
result->statusCode = instantiateVariableNode(server, session, &result->addedNodeId,
&item->typeDefinition.nodeId, instantiationCallback);
}
/* if instantiation failed, remove the node */
if(result->statusCode != UA_STATUSCODE_GOOD)
Service_DeleteNodes_single(server, session, &result->addedNodeId, true);
}
void Service_AddNodes(UA_Server *server, UA_Session *session, const UA_AddNodesRequest *request,
UA_AddNodesResponse *response) {
if(request->nodesToAddSize <= 0) {
response->responseHeader.serviceResult = UA_STATUSCODE_BADNOTHINGTODO;
return;
}
size_t size = request->nodesToAddSize;
response->results = UA_Array_new(size, &UA_TYPES[UA_TYPES_ADDNODESRESULT]);
if(!response->results) {
response->responseHeader.serviceResult = UA_STATUSCODE_BADOUTOFMEMORY;
return;
}
#ifdef UA_ENABLE_EXTERNAL_NAMESPACES
#ifdef _MSC_VER
UA_Boolean *isExternal = UA_alloca(size);
UA_UInt32 *indices = UA_alloca(sizeof(UA_UInt32)*size);
#else
UA_Boolean isExternal[size];
UA_UInt32 indices[size];
#endif
memset(isExternal, false, sizeof(UA_Boolean) * size);
for(size_t j = 0; j <server->externalNamespacesSize; j++) {
size_t indexSize = 0;
for(size_t i = 0;i < size;i++) {
if(request->nodesToAdd[i].requestedNewNodeId.nodeId.namespaceIndex !=
server->externalNamespaces[j].index)
continue;
isExternal[i] = true;
indices[indexSize] = i;
indexSize++;
}
if(indexSize == 0)
continue;
UA_ExternalNodeStore *ens = &server->externalNamespaces[j].externalNodeStore;
ens->addNodes(ens->ensHandle, &request->requestHeader, request->nodesToAdd,
indices, indexSize, response->results, response->diagnosticInfos);
}
#endif
response->resultsSize = size;
for(size_t i = 0; i < size; i++) {
#ifdef UA_ENABLE_EXTERNAL_NAMESPACES
if(!isExternal[i])
#endif
Service_AddNodes_single(server, session, &request->nodesToAdd[i], &response->results[i], NULL);
}
}
/**************************************************/
/* Add Special Nodes (not possible over the wire) */
/**************************************************/
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,
UA_NodeId *outNewNodeId) {
UA_AddNodesResult result;
UA_AddNodesResult_init(&result);
UA_AddNodesItem item;
UA_AddNodesItem_init(&item);
result.statusCode = UA_QualifiedName_copy(&browseName, &item.browseName);
item.nodeClass = UA_NODECLASS_VARIABLE;
result.statusCode |= UA_NodeId_copy(&parentNodeId, &item.parentNodeId.nodeId);
result.statusCode |= UA_NodeId_copy(&referenceTypeId, &item.referenceTypeId);
result.statusCode |= UA_NodeId_copy(&requestedNewNodeId, &item.requestedNewNodeId.nodeId);
result.statusCode |= UA_NodeId_copy(&typeDefinition, &item.typeDefinition.nodeId);
UA_VariableAttributes attrCopy;
result.statusCode |= UA_VariableAttributes_copy(&attr, &attrCopy);
if(result.statusCode != UA_STATUSCODE_GOOD) {
UA_AddNodesItem_deleteMembers(&item);
UA_VariableAttributes_deleteMembers(&attrCopy);
return result.statusCode;
}
UA_VariableNode *node = UA_NodeStore_newVariableNode();
if(!node) {
UA_AddNodesItem_deleteMembers(&item);
UA_VariableAttributes_deleteMembers(&attrCopy);
return UA_STATUSCODE_BADOUTOFMEMORY;
}
copyStandardAttributes((UA_Node*)node, &item, (UA_NodeAttributes*)&attrCopy);
node->valueSource = UA_VALUESOURCE_DATASOURCE;
node->value.dataSource = dataSource;
node->accessLevel = attr.accessLevel;
node->userAccessLevel = attr.userAccessLevel;
node->historizing = attr.historizing;
node->minimumSamplingInterval = attr.minimumSamplingInterval;
node->valueRank = attr.valueRank;
UA_RCU_LOCK();
Service_AddNodes_existing(server, &adminSession, (UA_Node*)node, &item.parentNodeId.nodeId,
&item.referenceTypeId, &result);
UA_RCU_UNLOCK();
UA_AddNodesItem_deleteMembers(&item);
UA_VariableAttributes_deleteMembers(&attrCopy);
if(outNewNodeId && result.statusCode == UA_STATUSCODE_GOOD)
*outNewNodeId = result.addedNodeId;
else
UA_AddNodesResult_deleteMembers(&result);
return result.statusCode;
}
#ifdef UA_ENABLE_METHODCALLS
UA_StatusCode
UA_Server_addMethodNode(UA_Server *server, const UA_NodeId requestedNewNodeId,
const UA_NodeId parentNodeId, const UA_NodeId referenceTypeId,
const UA_QualifiedName browseName, const UA_MethodAttributes attr,
UA_MethodCallback method, void *handle,
size_t inputArgumentsSize, const UA_Argument* inputArguments,
size_t outputArgumentsSize, const UA_Argument* outputArguments,
UA_NodeId *outNewNodeId) {
UA_AddNodesResult result;
UA_AddNodesResult_init(&result);
UA_AddNodesItem item;
UA_AddNodesItem_init(&item);
result.statusCode = UA_QualifiedName_copy(&browseName, &item.browseName);
item.nodeClass = UA_NODECLASS_METHOD;
result.statusCode |= UA_NodeId_copy(&parentNodeId, &item.parentNodeId.nodeId);
result.statusCode |= UA_NodeId_copy(&referenceTypeId, &item.referenceTypeId);
result.statusCode |= UA_NodeId_copy(&requestedNewNodeId, &item.requestedNewNodeId.nodeId);
UA_MethodAttributes attrCopy;
result.statusCode |= UA_MethodAttributes_copy(&attr, &attrCopy);
if(result.statusCode != UA_STATUSCODE_GOOD) {
UA_AddNodesItem_deleteMembers(&item);
UA_MethodAttributes_deleteMembers(&attrCopy);
return result.statusCode;
}
UA_MethodNode *node = UA_NodeStore_newMethodNode();
if(!node) {
result.statusCode = UA_STATUSCODE_BADOUTOFMEMORY;
UA_AddNodesItem_deleteMembers(&item);
UA_MethodAttributes_deleteMembers(&attrCopy);
return result.statusCode;
}
copyStandardAttributes((UA_Node*)node, &item, (UA_NodeAttributes*)&attrCopy);
node->executable = attrCopy.executable;
node->userExecutable = attrCopy.executable;
node->attachedMethod = method;
node->methodHandle = handle;
UA_AddNodesItem_deleteMembers(&item);
UA_MethodAttributes_deleteMembers(&attrCopy);
UA_RCU_LOCK();
Service_AddNodes_existing(server, &adminSession, (UA_Node*)node, &item.parentNodeId.nodeId,
&item.referenceTypeId, &result);
UA_RCU_UNLOCK();
if(result.statusCode != UA_STATUSCODE_GOOD)
return result.statusCode;
UA_ExpandedNodeId parent;
UA_ExpandedNodeId_init(&parent);
parent.nodeId = result.addedNodeId;
const UA_NodeId hasproperty = UA_NODEID_NUMERIC(0, UA_NS0ID_HASPROPERTY);
UA_VariableNode *inputArgumentsVariableNode = UA_NodeStore_newVariableNode();
inputArgumentsVariableNode->nodeId.namespaceIndex = result.addedNodeId.namespaceIndex;
inputArgumentsVariableNode->browseName = UA_QUALIFIEDNAME_ALLOC(0, "InputArguments");
inputArgumentsVariableNode->displayName = UA_LOCALIZEDTEXT_ALLOC("en_US", "InputArguments");
inputArgumentsVariableNode->description = UA_LOCALIZEDTEXT_ALLOC("en_US", "InputArguments");
inputArgumentsVariableNode->valueRank = 1;
UA_Variant_setArrayCopy(&inputArgumentsVariableNode->value.variant.value, inputArguments,
inputArgumentsSize, &UA_TYPES[UA_TYPES_ARGUMENT]);
UA_AddNodesResult inputAddRes;
UA_RCU_LOCK();
Service_AddNodes_existing(server, &adminSession, (UA_Node*)inputArgumentsVariableNode,
&parent.nodeId, &hasproperty, &inputAddRes);
UA_RCU_UNLOCK();
// todo: check if adding succeeded
UA_AddNodesResult_deleteMembers(&inputAddRes);
/* create OutputArguments */
UA_VariableNode *outputArgumentsVariableNode = UA_NodeStore_newVariableNode();
outputArgumentsVariableNode->nodeId.namespaceIndex = result.addedNodeId.namespaceIndex;
outputArgumentsVariableNode->browseName = UA_QUALIFIEDNAME_ALLOC(0, "OutputArguments");
outputArgumentsVariableNode->displayName = UA_LOCALIZEDTEXT_ALLOC("en_US", "OutputArguments");
outputArgumentsVariableNode->description = UA_LOCALIZEDTEXT_ALLOC("en_US", "OutputArguments");
outputArgumentsVariableNode->valueRank = 1;
UA_Variant_setArrayCopy(&outputArgumentsVariableNode->value.variant.value, outputArguments,
outputArgumentsSize, &UA_TYPES[UA_TYPES_ARGUMENT]);
UA_AddNodesResult outputAddRes;
UA_RCU_LOCK();
Service_AddNodes_existing(server, &adminSession, (UA_Node*)outputArgumentsVariableNode,
&parent.nodeId, &hasproperty, &outputAddRes);
UA_RCU_UNLOCK();
// todo: check if adding succeeded
UA_AddNodesResult_deleteMembers(&outputAddRes);
if(outNewNodeId)
*outNewNodeId = result.addedNodeId; // don't deleteMember the result
else
UA_AddNodesResult_deleteMembers(&result);
return result.statusCode;
}
#endif
/******************/
/* Add References */
/******************/
/* Adds a one-way reference to the local nodestore */
static UA_StatusCode
addOneWayReference(UA_Server *server, UA_Session *session, UA_Node *node, const UA_AddReferencesItem *item) {
size_t i = node->referencesSize;
size_t refssize = (i+1) | 3; // so the realloc is not necessary every time
UA_ReferenceNode *new_refs = UA_realloc(node->references, sizeof(UA_ReferenceNode) * refssize);
if(!new_refs)
return UA_STATUSCODE_BADOUTOFMEMORY;
node->references = new_refs;
UA_ReferenceNode_init(&new_refs[i]);
UA_StatusCode retval = UA_NodeId_copy(&item->referenceTypeId, &new_refs[i].referenceTypeId);
retval |= UA_ExpandedNodeId_copy(&item->targetNodeId, &new_refs[i].targetId);
new_refs[i].isInverse = !item->isForward;
if(retval == UA_STATUSCODE_GOOD)
node->referencesSize = i+1;
else
UA_ReferenceNode_deleteMembers(&new_refs[i]);
return retval;
}
UA_StatusCode
Service_AddReferences_single(UA_Server *server, UA_Session *session, const UA_AddReferencesItem *item) {
if(item->targetServerUri.length > 0)
return UA_STATUSCODE_BADNOTIMPLEMENTED; // currently no expandednodeids are allowed
/* cast away the const to loop the call through UA_Server_editNode */
UA_StatusCode retval = UA_Server_editNode(server, session, &item->sourceNodeId,
(UA_EditNodeCallback)addOneWayReference, item);
if(retval != UA_STATUSCODE_GOOD)
return retval;
UA_AddReferencesItem secondItem;
secondItem = *item;
secondItem.targetNodeId.nodeId = item->sourceNodeId;
secondItem.sourceNodeId = item->targetNodeId.nodeId;
secondItem.isForward = !item->isForward;
retval = UA_Server_editNode(server, session, &secondItem.sourceNodeId,
(UA_EditNodeCallback)addOneWayReference, &secondItem);
// todo: remove reference if the second direction failed
return retval;
}
void Service_AddReferences(UA_Server *server, UA_Session *session,
const UA_AddReferencesRequest *request,
UA_AddReferencesResponse *response) {
if(request->referencesToAddSize <= 0) {
response->responseHeader.serviceResult = UA_STATUSCODE_BADNOTHINGTODO;
return;
}
size_t size = request->referencesToAddSize;
if(!(response->results = UA_malloc(sizeof(UA_StatusCode) * size))) {
response->responseHeader.serviceResult = UA_STATUSCODE_BADOUTOFMEMORY;
return;
}
response->resultsSize = size;
#ifdef UA_ENABLE_EXTERNAL_NAMESPACES
#ifdef NO_ALLOCA
UA_Boolean isExternal[size];
UA_UInt32 indices[size];
#else
UA_Boolean *isExternal = UA_alloca(sizeof(UA_Boolean) * size);
UA_UInt32 *indices = UA_alloca(sizeof(UA_UInt32) * size);
#endif /*NO_ALLOCA */
memset(isExternal, false, sizeof(UA_Boolean) * size);
for(size_t j = 0; j < server->externalNamespacesSize; j++) {
size_t indicesSize = 0;
for(size_t i = 0;i < size;i++) {
if(request->referencesToAdd[i].sourceNodeId.namespaceIndex
!= server->externalNamespaces[j].index)
continue;
isExternal[i] = true;
indices[indicesSize] = i;
indicesSize++;
}
if (indicesSize == 0)
continue;
UA_ExternalNodeStore *ens = &server->externalNamespaces[j].externalNodeStore;
ens->addReferences(ens->ensHandle, &request->requestHeader, request->referencesToAdd,
indices, indicesSize, response->results, response->diagnosticInfos);
}
#endif
for(size_t i = 0; i < response->resultsSize; i++) {
#ifdef UA_ENABLE_EXTERNAL_NAMESPACES
if(!isExternal[i])
#endif
Service_AddReferences_single(server, session, &request->referencesToAdd[i]);
}
}
/****************/
/* Delete Nodes */
/****************/
// TODO: Check consistency constraints, remove the references.
UA_StatusCode
Service_DeleteNodes_single(UA_Server *server, UA_Session *session, const UA_NodeId *nodeId,
UA_Boolean deleteReferences) {
const UA_Node *node = UA_NodeStore_get(server->nodestore, nodeId);
if(!node)
return UA_STATUSCODE_BADNODEIDINVALID;
if(deleteReferences == true) {
UA_DeleteReferencesItem delItem;
UA_DeleteReferencesItem_init(&delItem);
delItem.deleteBidirectional = false;
delItem.targetNodeId.nodeId = *nodeId;
for(size_t i = 0; i < node->referencesSize; i++) {
delItem.sourceNodeId = node->references[i].targetId.nodeId;
delItem.isForward = node->references[i].isInverse;
Service_DeleteReferences_single(server, session, &delItem);
}
}
/* destroy an object before removing it */
if(node->nodeClass == UA_NODECLASS_OBJECT) {
/* find the object type(s) */
UA_BrowseDescription bd;
UA_BrowseDescription_init(&bd);
bd.browseDirection = UA_BROWSEDIRECTION_INVERSE;
bd.nodeId = *nodeId;
bd.referenceTypeId = UA_NODEID_NUMERIC(0, UA_NS0ID_HASSUBTYPE);
bd.includeSubtypes = true;
bd.nodeClassMask = UA_NODECLASS_OBJECTTYPE;
/* browse type definitions with admin rights */
UA_BrowseResult result;
UA_BrowseResult_init(&result);
Service_Browse_single(server, &adminSession, NULL, &bd, UA_UINT32_MAX, &result);
for(size_t i = 0; i < result.referencesSize; i++) {
/* call the destructor */
UA_ReferenceDescription *rd = &result.references[i];
const UA_ObjectTypeNode *typenode =
(const UA_ObjectTypeNode*)UA_NodeStore_get(server->nodestore, &rd->nodeId.nodeId);
if(!typenode)
continue;
if(typenode->nodeClass != UA_NODECLASS_OBJECTTYPE || !typenode->lifecycleManagement.destructor)
continue;
/* if there are several types with lifecycle management, call all the destructors */
typenode->lifecycleManagement.destructor(*nodeId, ((const UA_ObjectNode*)node)->instanceHandle);
}
UA_BrowseResult_deleteMembers(&result);
}
return UA_NodeStore_remove(server->nodestore, nodeId);
}
void Service_DeleteNodes(UA_Server *server, UA_Session *session, const UA_DeleteNodesRequest *request,
UA_DeleteNodesResponse *response) {
if(request->nodesToDeleteSize <= 0) {
response->responseHeader.serviceResult = UA_STATUSCODE_BADNOTHINGTODO;
return;
}
response->results = UA_malloc(sizeof(UA_StatusCode) * request->nodesToDeleteSize);
if(!response->results) {
response->responseHeader.serviceResult = UA_STATUSCODE_BADOUTOFMEMORY;;
return;
}
response->resultsSize = request->nodesToDeleteSize;
for(size_t i=0; i<request->nodesToDeleteSize; i++) {
UA_DeleteNodesItem *item = &request->nodesToDelete[i];
response->results[i] = Service_DeleteNodes_single(server, session, &item->nodeId,
item->deleteTargetReferences);
}
}
/*********************/
/* Delete References */
/*********************/
static UA_StatusCode
deleteOneWayReference(UA_Server *server, UA_Session *session, UA_Node *node,
const UA_DeleteReferencesItem *item) {
UA_Boolean edited = false;
for(size_t i = node->referencesSize - 1; ; i--) {
if(i > node->referencesSize)
break; /* underflow after i == 0 */
if(!UA_NodeId_equal(&item->targetNodeId.nodeId, &node->references[i].targetId.nodeId))
continue;
if(!UA_NodeId_equal(&item->referenceTypeId, &node->references[i].referenceTypeId))
continue;
if(item->isForward == node->references[i].isInverse)
continue;
/* move the last entry to override the current position */
UA_ReferenceNode_deleteMembers(&node->references[i]);
node->references[i] = node->references[node->referencesSize-1];
node->referencesSize--;
edited = true;
break;
}
if(!edited)
return UA_STATUSCODE_UNCERTAINREFERENCENOTDELETED;
/* we removed the last reference */
if(node->referencesSize == 0 && node->references)
UA_free(node->references);
return UA_STATUSCODE_GOOD;;
}
UA_StatusCode
Service_DeleteReferences_single(UA_Server *server, UA_Session *session,
const UA_DeleteReferencesItem *item) {
UA_StatusCode retval = UA_Server_editNode(server, session, &item->sourceNodeId,
(UA_EditNodeCallback)deleteOneWayReference, item);
if(!item->deleteBidirectional || item->targetNodeId.serverIndex != 0)
return retval;
UA_DeleteReferencesItem secondItem;
UA_DeleteReferencesItem_init(&secondItem);
secondItem.isForward = !item->isForward;
secondItem.sourceNodeId = item->targetNodeId.nodeId;
secondItem.targetNodeId.nodeId = item->sourceNodeId;
return 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) {
if(request->referencesToDeleteSize <= 0) {
response->responseHeader.serviceResult = UA_STATUSCODE_BADNOTHINGTODO;
return;
}
response->results = UA_malloc(sizeof(UA_StatusCode) * request->referencesToDeleteSize);
if(!response->results) {
response->responseHeader.serviceResult = UA_STATUSCODE_BADOUTOFMEMORY;;
return;
}
response->resultsSize = request->referencesToDeleteSize;
for(size_t i = 0; i < request->referencesToDeleteSize; i++)
response->results[i] =
Service_DeleteReferences_single(server, session, &request->referencesToDelete[i]);
}
/*********************************** amalgamated original file "/home/wn/Sources/open62541-open62541-395ce48/src/server/ua_services_view.c" ***********************************/
static UA_StatusCode
fillReferenceDescription(UA_NodeStore *ns, const UA_Node *curr, UA_ReferenceNode *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) {
for(size_t i = 0; i < curr->referencesSize; i++) {
UA_ReferenceNode *refnode = &curr->references[i];
if(refnode->referenceTypeId.identifier.numeric != UA_NS0ID_HASTYPEDEFINITION)
continue;
retval |= UA_ExpandedNodeId_copy(&refnode->targetId, &descr->typeDefinition);
break;
}
}
}
return retval;
}
#ifdef UA_ENABLE_EXTERNAL_NAMESPACES
static const UA_Node *
returnRelevantNodeExternal(UA_ExternalNodeStore *ens, const UA_BrowseDescription *descr,
const UA_ReferenceNode *reference) {
/* prepare a read request in the external nodestore */
UA_ReadValueId *readValueIds = UA_Array_new(6,&UA_TYPES[UA_TYPES_READVALUEID]);
UA_UInt32 *indices = UA_Array_new(6,&UA_TYPES[UA_TYPES_UINT32]);
UA_UInt32 indicesSize = 6;
UA_DataValue *readNodesResults = UA_Array_new(6,&UA_TYPES[UA_TYPES_DATAVALUE]);
UA_DiagnosticInfo *diagnosticInfos = UA_Array_new(6,&UA_TYPES[UA_TYPES_DIAGNOSTICINFO]);
for(UA_UInt32 i = 0; i < 6; i++) {
readValueIds[i].nodeId = reference->targetId.nodeId;
indices[i] = i;
}
readValueIds[0].attributeId = UA_ATTRIBUTEID_NODECLASS;
readValueIds[1].attributeId = UA_ATTRIBUTEID_BROWSENAME;
readValueIds[2].attributeId = UA_ATTRIBUTEID_DISPLAYNAME;
readValueIds[3].attributeId = UA_ATTRIBUTEID_DESCRIPTION;
readValueIds[4].attributeId = UA_ATTRIBUTEID_WRITEMASK;
readValueIds[5].attributeId = UA_ATTRIBUTEID_USERWRITEMASK;
ens->readNodes(ens->ensHandle, NULL, readValueIds, indices,
indicesSize, readNodesResults, false, diagnosticInfos);
/* create and fill a dummy nodeStructure */
UA_Node *node = (UA_Node*) UA_NodeStore_newObjectNode();
UA_NodeId_copy(&(reference->targetId.nodeId), &(node->nodeId));
if(readNodesResults[0].status == UA_STATUSCODE_GOOD)
UA_NodeClass_copy((UA_NodeClass*)readNodesResults[0].value.data, &(node->nodeClass));
if(readNodesResults[1].status == UA_STATUSCODE_GOOD)
UA_QualifiedName_copy((UA_QualifiedName*)readNodesResults[1].value.data, &(node->browseName));
if(readNodesResults[2].status == UA_STATUSCODE_GOOD)
UA_LocalizedText_copy((UA_LocalizedText*)readNodesResults[2].value.data, &(node->displayName));
if(readNodesResults[3].status == UA_STATUSCODE_GOOD)
UA_LocalizedText_copy((UA_LocalizedText*)readNodesResults[3].value.data, &(node->description));
if(readNodesResults[4].status == UA_STATUSCODE_GOOD)
UA_UInt32_copy((UA_UInt32*)readNodesResults[4].value.data, &(node->writeMask));
if(readNodesResults[5].status == UA_STATUSCODE_GOOD)
UA_UInt32_copy((UA_UInt32*)readNodesResults[5].value.data, &(node->userWriteMask));
UA_Array_delete(readValueIds,6, &UA_TYPES[UA_TYPES_READVALUEID]);
UA_Array_delete(indices,6, &UA_TYPES[UA_TYPES_UINT32]);
UA_Array_delete(readNodesResults,6, &UA_TYPES[UA_TYPES_DATAVALUE]);
UA_Array_delete(diagnosticInfos,6, &UA_TYPES[UA_TYPES_DIAGNOSTICINFO]);
if(node && descr->nodeClassMask != 0 && (node->nodeClass & descr->nodeClassMask) == 0) {
UA_NodeStore_deleteNode(node);
return NULL;
}
return node;
}
#endif
/* Tests if the node is relevant to the browse request and shall be returned. If
so, it is retrieved from the Nodestore. If not, null is returned. */
static const UA_Node *
returnRelevantNode(UA_Server *server, const UA_BrowseDescription *descr, UA_Boolean return_all,
const UA_ReferenceNode *reference, const UA_NodeId *relevant, size_t relevant_count,
UA_Boolean *isExternal) {
/* reference in the right direction? */
if(reference->isInverse && descr->browseDirection == UA_BROWSEDIRECTION_FORWARD)
return NULL;
if(!reference->isInverse && descr->browseDirection == UA_BROWSEDIRECTION_INVERSE)
return NULL;
/* is the reference part of the hierarchy of references we look for? */
if(!return_all) {
UA_Boolean is_relevant = false;
for(size_t i = 0; i < relevant_count; i++) {
if(UA_NodeId_equal(&reference->referenceTypeId, &relevant[i])) {
is_relevant = true;
break;
}
}
if(!is_relevant)
return NULL;
}
#ifdef UA_ENABLE_EXTERNAL_NAMESPACES
/* return the node from an external namespace*/
for(size_t nsIndex = 0; nsIndex < server->externalNamespacesSize; nsIndex++) {
if(reference->targetId.nodeId.namespaceIndex != server->externalNamespaces[nsIndex].index)
continue;
*isExternal = true;
return returnRelevantNodeExternal(&server->externalNamespaces[nsIndex].externalNodeStore,
descr, reference);
}
#endif
/* return from the internal nodestore */
const UA_Node *node = UA_NodeStore_get(server->nodestore, &reference->targetId.nodeId);
if(node && descr->nodeClassMask != 0 && (node->nodeClass & descr->nodeClassMask) == 0)
return NULL;
*isExternal = false;
return node;
}
/**
* We find all subtypes by a single iteration over the array. We start with an array with a single
* root nodeid at the beginning. When we find relevant references, we add the nodeids to the back of
* the array and increase the size. Since the hierarchy is not cyclic, we can safely progress in the
* array to process the newly found referencetype nodeids (emulated recursion).
*/
static UA_StatusCode
findSubTypes(UA_NodeStore *ns, const UA_NodeId *root, UA_NodeId **reftypes, size_t *reftypes_count) {
const UA_Node *node = UA_NodeStore_get(ns, root);
if(!node)
return UA_STATUSCODE_BADNOMATCH;
if(node->nodeClass != UA_NODECLASS_REFERENCETYPE)
return UA_STATUSCODE_BADREFERENCETYPEIDINVALID;
size_t results_size = 20; // probably too big, but saves mallocs
UA_NodeId *results = UA_malloc(sizeof(UA_NodeId) * results_size);
if(!results)
return UA_STATUSCODE_BADOUTOFMEMORY;
UA_StatusCode retval = UA_NodeId_copy(root, &results[0]);
if(retval != UA_STATUSCODE_GOOD) {
UA_free(results);
return retval;
}
size_t idx = 0; // where are we currently in the array?
size_t last = 0; // where is the last element in the array?
do {
node = UA_NodeStore_get(ns, &results[idx]);
if(!node || node->nodeClass != UA_NODECLASS_REFERENCETYPE)
continue;
for(size_t i = 0; i < node->referencesSize; i++) {
if(node->references[i].referenceTypeId.identifier.numeric != UA_NS0ID_HASSUBTYPE ||
node->references[i].isInverse == true)
continue;
if(++last >= results_size) { // is the array big enough?
UA_NodeId *new_results = UA_realloc(results, sizeof(UA_NodeId) * results_size * 2);
if(!new_results) {
retval = UA_STATUSCODE_BADOUTOFMEMORY;
break;
}
results = new_results;
results_size *= 2;
}
retval = UA_NodeId_copy(&node->references[i].targetId.nodeId, &results[last]);
if(retval != UA_STATUSCODE_GOOD) {
last--; // for array_delete
break;
}
}
} while(++idx <= last && retval == UA_STATUSCODE_GOOD);
if(retval != UA_STATUSCODE_GOOD) {
UA_Array_delete(results, last, &UA_TYPES[UA_TYPES_NODEID]);
return retval;
}
*reftypes = results;
*reftypes_count = last + 1;
return UA_STATUSCODE_GOOD;
}
static void removeCp(struct ContinuationPointEntry *cp, UA_Session* session) {
LIST_REMOVE(cp, pointers);
UA_ByteString_deleteMembers(&cp->identifier);
UA_BrowseDescription_deleteMembers(&cp->browseDescription);
UA_free(cp);
session->availableContinuationPoints++;
}
/**
* Results for a single browsedescription. This is the inner loop for both Browse and BrowseNext
* @param session Session to save continuationpoints
* @param ns The nodstore where the to-be-browsed node can be found
* @param cp If cp is not null, we continue from here
* If cp is null, we can add a new continuation point if possible and necessary.
* @param descr If no cp is set, we take the browsedescription from there
* @param maxrefs The maximum number of references the client has requested
* @param result The entry in the request
*/
void
Service_Browse_single(UA_Server *server, UA_Session *session, struct ContinuationPointEntry *cp,
const UA_BrowseDescription *descr, UA_UInt32 maxrefs, UA_BrowseResult *result) {
size_t referencesCount = 0;
size_t referencesIndex = 0;
/* set the browsedescription if a cp is given */
UA_UInt32 continuationIndex = 0;
if(cp) {
descr = &cp->browseDescription;
maxrefs = cp->maxReferences;
continuationIndex = cp->continuationIndex;
}
/* 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;
}
/* get the references that match the browsedescription */
size_t relevant_refs_size = 0;
UA_NodeId *relevant_refs = NULL;
UA_Boolean all_refs = UA_NodeId_isNull(&descr->referenceTypeId);
if(!all_refs) {
if(descr->includeSubtypes) {
result->statusCode = findSubTypes(server->nodestore, &descr->referenceTypeId,
&relevant_refs, &relevant_refs_size);
if(result->statusCode != UA_STATUSCODE_GOOD)
return;
} else {
const UA_Node *rootRef = UA_NodeStore_get(server->nodestore, &descr->referenceTypeId);
if(!rootRef || rootRef->nodeClass != UA_NODECLASS_REFERENCETYPE) {
result->statusCode = UA_STATUSCODE_BADREFERENCETYPEIDINVALID;
return;
}
relevant_refs = (UA_NodeId*)(uintptr_t)&descr->referenceTypeId;
relevant_refs_size = 1;
}
}
/* get the node */
const UA_Node *node = UA_NodeStore_get(server->nodestore, &descr->nodeId);
if(!node) {
result->statusCode = UA_STATUSCODE_BADNODEIDUNKNOWN;
if(!all_refs && descr->includeSubtypes)
UA_Array_delete(relevant_refs, relevant_refs_size, &UA_TYPES[UA_TYPES_NODEID]);
return;
}
/* if the node has no references, just return */
if(node->referencesSize == 0) {
result->referencesSize = 0;
if(!all_refs && descr->includeSubtypes)
UA_Array_delete(relevant_refs, relevant_refs_size, &UA_TYPES[UA_TYPES_NODEID]);
return;
}
/* how many references can we return at most? */
size_t real_maxrefs = maxrefs;
if(real_maxrefs == 0)
real_maxrefs = node->referencesSize;
if(node->referencesSize == 0)
real_maxrefs = 0;
else if(real_maxrefs > node->referencesSize)
real_maxrefs = node->referencesSize;
result->references = UA_Array_new(real_maxrefs, &UA_TYPES[UA_TYPES_REFERENCEDESCRIPTION]);
if(!result->references) {
result->statusCode = UA_STATUSCODE_BADOUTOFMEMORY;
goto cleanup;
}
/* loop over the node's references */
size_t skipped = 0;
UA_Boolean isExternal = false;
UA_StatusCode retval = UA_STATUSCODE_GOOD;
for(; referencesIndex < node->referencesSize && referencesCount < real_maxrefs; referencesIndex++) {
isExternal = false;
const UA_Node *current =
returnRelevantNode(server, descr, all_refs, &node->references[referencesIndex],
relevant_refs, relevant_refs_size, &isExternal);
if(!current)
continue;
if(skipped < continuationIndex) {
skipped++;
} else {
retval |= fillReferenceDescription(server->nodestore, current, &node->references[referencesIndex],
descr->resultMask, &result->references[referencesCount]);
referencesCount++;
}
#ifdef UA_ENABLE_EXTERNAL_NAMESPACES
/* relevant_node returns a node malloced by the nodestore.
if it is external (there is no UA_Node_new function) */
// if(isExternal == true)
// UA_Node_deleteMembersAnyNodeClass(current);
//TODO something's wrong here...
#endif
}
result->referencesSize = referencesCount;
if(referencesCount == 0) {
UA_free(result->references);
result->references = NULL;
}
if(retval != UA_STATUSCODE_GOOD) {
UA_Array_delete(result->references, result->referencesSize, &UA_TYPES[UA_TYPES_REFERENCEDESCRIPTION]);
result->references = NULL;
result->referencesSize = 0;
result->statusCode = retval;
}
cleanup:
if(!all_refs && descr->includeSubtypes)
UA_Array_delete(relevant_refs, relevant_refs_size, &UA_TYPES[UA_TYPES_NODEID]);
if(result->statusCode != UA_STATUSCODE_GOOD)
return;
/* create, update, delete continuation points */
if(cp) {
if(referencesIndex == node->referencesSize) {
/* all done, remove a finished continuationPoint */
removeCp(cp, session);
} else {
/* update the cp and return the cp identifier */
cp->continuationIndex += (UA_UInt32)referencesCount;
UA_ByteString_copy(&cp->identifier, &result->continuationPoint);
}
} else if(maxrefs != 0 && referencesCount >= maxrefs) {
/* create a cp */
if(session->availableContinuationPoints <= 0 ||
!(cp = UA_malloc(sizeof(struct ContinuationPointEntry)))) {
result->statusCode = UA_STATUSCODE_BADNOCONTINUATIONPOINTS;
return;
}
UA_BrowseDescription_copy(descr, &cp->browseDescription);
cp->maxReferences = maxrefs;
cp->continuationIndex = (UA_UInt32)referencesCount;
UA_Guid *ident = UA_Guid_new();
*ident = UA_Guid_random();
cp->identifier.data = (UA_Byte*)ident;
cp->identifier.length = sizeof(UA_Guid);
UA_ByteString_copy(&cp->identifier, &result->continuationPoint);
/* store the cp */
LIST_INSERT_HEAD(&session->continuationPoints, cp, pointers);
session->availableContinuationPoints--;
}
}
void Service_Browse(UA_Server *server, UA_Session *session, const UA_BrowseRequest *request,
UA_BrowseResponse *response) {
UA_LOG_DEBUG(server->config.logger, UA_LOGCATEGORY_SESSION,
"Processing BrowseRequest for Session (ns=%i,i=%i)",
session->sessionId.namespaceIndex, session->sessionId.identifier.numeric);
if(!UA_NodeId_isNull(&request->view.viewId)) {
response->responseHeader.serviceResult = UA_STATUSCODE_BADVIEWIDUNKNOWN;
return;
}
if(request->nodesToBrowseSize <= 0) {
response->responseHeader.serviceResult = UA_STATUSCODE_BADNOTHINGTODO;
return;
}
size_t size = request->nodesToBrowseSize;
response->results = UA_Array_new(size, &UA_TYPES[UA_TYPES_BROWSERESULT]);
if(!response->results) {
response->responseHeader.serviceResult = UA_STATUSCODE_BADOUTOFMEMORY;
return;
}
response->resultsSize = size;
#ifdef UA_ENABLE_EXTERNAL_NAMESPACES
#ifdef NO_ALLOCA
UA_Boolean isExternal[size];
UA_UInt32 indices[size];
#else
UA_Boolean *isExternal = UA_alloca(sizeof(UA_Boolean) * size);
UA_UInt32 *indices = UA_alloca(sizeof(UA_UInt32) * size);
#endif /*NO_ALLOCA */
memset(isExternal, false, sizeof(UA_Boolean) * size);
for(size_t j = 0; j < server->externalNamespacesSize; j++) {
size_t indexSize = 0;
for(size_t i = 0; i < size; i++) {
if(request->nodesToBrowse[i].nodeId.namespaceIndex != server->externalNamespaces[j].index)
continue;
isExternal[i] = true;
indices[indexSize] = i;
indexSize++;
}
if(indexSize == 0)
continue;
UA_ExternalNodeStore *ens = &server->externalNamespaces[j].externalNodeStore;
ens->browseNodes(ens->ensHandle, &request->requestHeader, request->nodesToBrowse, indices, indexSize,
request->requestedMaxReferencesPerNode, response->results, response->diagnosticInfos);
}
#endif
for(size_t i = 0; i < size; i++) {
#ifdef UA_ENABLE_EXTERNAL_NAMESPACES
if(!isExternal[i])
#endif
Service_Browse_single(server, session, NULL, &request->nodesToBrowse[i],
request->requestedMaxReferencesPerNode, &response->results[i]);
}
}
void
UA_Server_browseNext_single(UA_Server *server, UA_Session *session, UA_Boolean releaseContinuationPoint,
const UA_ByteString *continuationPoint, UA_BrowseResult *result) {
result->statusCode = UA_STATUSCODE_BADCONTINUATIONPOINTINVALID;
struct ContinuationPointEntry *cp, *temp;
LIST_FOREACH_SAFE(cp, &session->continuationPoints, pointers, temp) {
if(UA_ByteString_equal(&cp->identifier, continuationPoint)) {
result->statusCode = UA_STATUSCODE_GOOD;
if(!releaseContinuationPoint)
Service_Browse_single(server, session, cp, NULL, 0, result);
else
removeCp(cp, session);
break;
}
}
}
void Service_BrowseNext(UA_Server *server, UA_Session *session, const UA_BrowseNextRequest *request,
UA_BrowseNextResponse *response) {
UA_LOG_DEBUG(server->config.logger, UA_LOGCATEGORY_SESSION,
"Processing BrowseNextRequest for Session (ns=%i,i=%i)",
session->sessionId.namespaceIndex, session->sessionId.identifier.numeric);
if(request->continuationPointsSize <= 0) {
response->responseHeader.serviceResult = UA_STATUSCODE_BADNOTHINGTODO;
return;
}
size_t size = request->continuationPointsSize;
response->results = UA_Array_new(size, &UA_TYPES[UA_TYPES_BROWSERESULT]);
if(!response->results) {
response->responseHeader.serviceResult = UA_STATUSCODE_BADOUTOFMEMORY;
return;
}
response->resultsSize = size;
for(size_t i = 0; i < size; i++)
UA_Server_browseNext_single(server, session, request->releaseContinuationPoints,
&request->continuationPoints[i], &response->results[i]);
}
/***********************/
/* TranslateBrowsePath */
/***********************/
static UA_StatusCode
walkBrowsePath(UA_Server *server, UA_Session *session, const UA_Node *node, const UA_RelativePath *path,
size_t pathindex, UA_BrowsePathTarget **targets, size_t *targets_size,
size_t *target_count) {
const UA_RelativePathElement *elem = &path->elements[pathindex];
UA_StatusCode retval = UA_STATUSCODE_GOOD;
UA_NodeId *reftypes = NULL;
size_t reftypes_count = 1; // all_refs or no subtypes => 1
UA_Boolean all_refs = false;
if(UA_NodeId_isNull(&elem->referenceTypeId))
all_refs = true;
else if(!elem->includeSubtypes)
reftypes = (UA_NodeId*)(uintptr_t)&elem->referenceTypeId; // ptr magic due to const cast
else {
retval = findSubTypes(server->nodestore, &elem->referenceTypeId, &reftypes, &reftypes_count);
if(retval != UA_STATUSCODE_GOOD)
return retval;
}
for(size_t i = 0; i < node->referencesSize && retval == UA_STATUSCODE_GOOD; i++) {
UA_Boolean match = all_refs;
for(size_t j = 0; j < reftypes_count && !match; j++) {
if(node->references[i].isInverse == elem->isInverse &&
UA_NodeId_equal(&node->references[i].referenceTypeId, &reftypes[j]))
match = true;
}
if(!match)
continue;
// get the node, todo: expandednodeid
const UA_Node *next = UA_NodeStore_get(server->nodestore, &node->references[i].targetId.nodeId);
if(!next)
continue;
// test the browsename
if(elem->targetName.namespaceIndex != next->browseName.namespaceIndex ||
!UA_String_equal(&elem->targetName.name, &next->browseName.name)) {
continue;
}
if(pathindex + 1 < path->elementsSize) {
// recursion if the path is longer
retval = walkBrowsePath(server, session, next, path, pathindex + 1,
targets, targets_size, target_count);
} else {
// add the browsetarget
if(*target_count >= *targets_size) {
UA_BrowsePathTarget *newtargets;
newtargets = UA_realloc(targets, sizeof(UA_BrowsePathTarget) * (*targets_size) * 2);
if(!newtargets) {
retval = UA_STATUSCODE_BADOUTOFMEMORY;
break;
}
*targets = newtargets;
*targets_size *= 2;
}
UA_BrowsePathTarget *res = *targets;
UA_ExpandedNodeId_init(&res[*target_count].targetId);
retval = UA_NodeId_copy(&next->nodeId, &res[*target_count].targetId.nodeId);
if(retval != UA_STATUSCODE_GOOD)
break;
res[*target_count].remainingPathIndex = UA_UINT32_MAX;
*target_count += 1;
}
}
if(!all_refs && elem->includeSubtypes)
UA_Array_delete(reftypes, reftypes_count, &UA_TYPES[UA_TYPES_NODEID]);
return retval;
}
void Service_TranslateBrowsePathsToNodeIds_single(UA_Server *server, UA_Session *session,
const UA_BrowsePath *path, UA_BrowsePathResult *result) {
if(path->relativePath.elementsSize <= 0) {
result->statusCode = UA_STATUSCODE_BADNOTHINGTODO;
return;
}
size_t arraySize = 10;
result->targets = UA_malloc(sizeof(UA_BrowsePathTarget) * arraySize);
if(!result->targets) {
result->statusCode = UA_STATUSCODE_BADOUTOFMEMORY;
return;
}
result->targetsSize = 0;
const UA_Node *firstNode = UA_NodeStore_get(server->nodestore, &path->startingNode);
if(!firstNode) {
result->statusCode = UA_STATUSCODE_BADNODEIDUNKNOWN;
UA_free(result->targets);
result->targets = NULL;
return;
}
result->statusCode = walkBrowsePath(server, session, firstNode, &path->relativePath, 0,
&result->targets, &arraySize, &result->targetsSize);
if(result->targetsSize == 0 && result->statusCode == UA_STATUSCODE_GOOD)
result->statusCode = UA_STATUSCODE_BADNOMATCH;
if(result->statusCode != UA_STATUSCODE_GOOD) {
UA_Array_delete(result->targets, result->targetsSize, &UA_TYPES[UA_TYPES_BROWSEPATHTARGET]);
result->targets = NULL;
result->targetsSize = 0;
}
}
void Service_TranslateBrowsePathsToNodeIds(UA_Server *server, UA_Session *session,
const UA_TranslateBrowsePathsToNodeIdsRequest *request,
UA_TranslateBrowsePathsToNodeIdsResponse *response) {
UA_LOG_DEBUG(server->config.logger, UA_LOGCATEGORY_SESSION,
"Processing TranslateBrowsePathsToNodeIdsRequest for Session (ns=%i,i=%i)",
session->sessionId.namespaceIndex, session->sessionId.identifier.numeric);
if(request->browsePathsSize <= 0) {
response->responseHeader.serviceResult = UA_STATUSCODE_BADNOTHINGTODO;
return;
}
size_t size = request->browsePathsSize;
response->results = UA_Array_new(size, &UA_TYPES[UA_TYPES_BROWSEPATHRESULT]);
if(!response->results) {
response->responseHeader.serviceResult = UA_STATUSCODE_BADOUTOFMEMORY;
return;
}
#ifdef UA_ENABLE_EXTERNAL_NAMESPACES
#ifdef NO_ALLOCA
UA_Boolean isExternal[size];
UA_UInt32 indices[size];
#else
UA_Boolean *isExternal = UA_alloca(sizeof(UA_Boolean) * size);
UA_UInt32 *indices = UA_alloca(sizeof(UA_UInt32) * size);
#endif /*NO_ALLOCA */
memset(isExternal, false, sizeof(UA_Boolean) * size);
for(size_t j = 0; j < server->externalNamespacesSize; j++) {
size_t indexSize = 0;
for(size_t i = 0;i < size;i++) {
if(request->browsePaths[i].startingNode.namespaceIndex != server->externalNamespaces[j].index)
continue;
isExternal[i] = true;
indices[indexSize] = i;
indexSize++;
}
if(indexSize == 0)
continue;
UA_ExternalNodeStore *ens = &server->externalNamespaces[j].externalNodeStore;
ens->translateBrowsePathsToNodeIds(ens->ensHandle, &request->requestHeader, request->browsePaths,
indices, indexSize, response->results, response->diagnosticInfos);
}
#endif
response->resultsSize = size;
for(size_t i = 0; i < size; i++) {
#ifdef UA_ENABLE_EXTERNAL_NAMESPACES
if(!isExternal[i])
#endif
Service_TranslateBrowsePathsToNodeIds_single(server, session, &request->browsePaths[i],
&response->results[i]);
}
}
void Service_RegisterNodes(UA_Server *server, UA_Session *session, const UA_RegisterNodesRequest *request,
UA_RegisterNodesResponse *response) {
UA_LOG_DEBUG(server->config.logger, UA_LOGCATEGORY_SESSION,
"Processing RegisterNodesRequest for Session (ns=%i,i=%i)",
session->sessionId.namespaceIndex, session->sessionId.identifier.numeric);
//TODO: hang the nodeids to the session if really needed
response->responseHeader.timestamp = UA_DateTime_now();
if(request->nodesToRegisterSize <= 0)
response->responseHeader.serviceResult = UA_STATUSCODE_BADNOTHINGTODO;
else {
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(server->config.logger, UA_LOGCATEGORY_SESSION,
"Processing UnRegisterNodesRequest for Session (ns=%i,i=%i)",
session->sessionId.namespaceIndex, session->sessionId.identifier.numeric);
//TODO: remove the nodeids from the session if really needed
response->responseHeader.timestamp = UA_DateTime_now();
if(request->nodesToUnregisterSize==0)
response->responseHeader.serviceResult = UA_STATUSCODE_BADNOTHINGTODO;
}
/*********************************** amalgamated original file "/home/wn/Sources/open62541-open62541-395ce48/src/client/ua_client.c" ***********************************/
/*********************/
/* Create and Delete */
/*********************/
static void UA_Client_init(UA_Client* client, UA_ClientConfig config) {
client->state = UA_CLIENTSTATE_READY;
UA_Connection_init(&client->connection);
UA_SecureChannel_init(&client->channel);
client->channel.connection = &client->connection;
UA_String_init(&client->endpointUrl);
client->requestId = 0;
client->authenticationMethod = UA_CLIENTAUTHENTICATION_NONE;
UA_String_init(&client->username);
UA_String_init(&client->password);
UA_NodeId_init(&client->authenticationToken);
client->requestHandle = 0;
client->config = config;
client->scRenewAt = 0;
#ifdef UA_ENABLE_SUBSCRIPTIONS
client->monitoredItemHandles = 0;
LIST_INIT(&client->pendingNotificationsAcks);
LIST_INIT(&client->subscriptions);
#endif
}
UA_Client * UA_Client_new(UA_ClientConfig config) {
UA_Client *client = UA_calloc(1, 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);
UA_Connection_deleteMembers(&client->connection);
UA_SecureChannel_deleteMembersCleanup(&client->channel);
if(client->endpointUrl.data)
UA_String_deleteMembers(&client->endpointUrl);
UA_UserTokenPolicy_deleteMembers(&client->token);
if(client->username.data)
UA_String_deleteMembers(&client->username);
if(client->password.data)
UA_String_deleteMembers(&client->password);
#ifdef UA_ENABLE_SUBSCRIPTIONS
UA_Client_NotificationsAckNumber *n, *tmp;
LIST_FOREACH_SAFE(n, &client->pendingNotificationsAcks, listEntry, tmp) {
LIST_REMOVE(n, listEntry);
free(n);
}
UA_Client_Subscription *sub, *tmps;
LIST_FOREACH_SAFE(sub, &client->subscriptions, listEntry, tmps) {
LIST_REMOVE(sub, listEntry);
UA_Client_MonitoredItem *mon, *tmpmon;
LIST_FOREACH_SAFE(mon, &sub->MonitoredItems, listEntry, tmpmon) {
UA_Client_Subscriptions_removeMonitoredItem(client, sub->SubscriptionID,
mon->MonitoredItemId);
}
free(sub);
}
#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){
if(client->state != UA_CLIENTSTATE_READY)
UA_Client_deleteMembers(client);
UA_free(client);
}
UA_ClientState UA_EXPORT UA_Client_getState(UA_Client *client) {
if (client == NULL)
return UA_CLIENTSTATE_ERRORED;
return client->state;
}
/*************************/
/* Manage the Connection */
/*************************/
static UA_StatusCode HelAckHandshake(UA_Client *client) {
UA_TcpMessageHeader messageHeader;
messageHeader.messageTypeAndChunkType = UA_CHUNKTYPE_FINAL + UA_MESSAGETYPE_HEL;
UA_TcpHelloMessage hello;
UA_String_copy(&client->endpointUrl, &hello.endpointUrl); /* must be less than 4096 bytes */
UA_Connection *conn = &client->connection;
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_ByteString message;
UA_StatusCode retval;
retval = client->connection.getSendBuffer(&client->connection, client->connection.remoteConf.recvBufferSize, &message);
if(retval != UA_STATUSCODE_GOOD)
return retval;
size_t offset = 8;
retval |= UA_TcpHelloMessage_encodeBinary(&hello, &message, &offset);
messageHeader.messageSize = (UA_UInt32)offset;
offset = 0;
retval |= UA_TcpMessageHeader_encodeBinary(&messageHeader, &message, &offset);
UA_TcpHelloMessage_deleteMembers(&hello);
if(retval != UA_STATUSCODE_GOOD) {
client->connection.releaseSendBuffer(&client->connection, &message);
return retval;
}
message.length = messageHeader.messageSize;
retval = client->connection.send(&client->connection, &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");
UA_ByteString reply;
UA_ByteString_init(&reply);
UA_Boolean realloced = false;
do {
retval = client->connection.recv(&client->connection, &reply, client->config.timeout);
retval |= UA_Connection_completeMessages(&client->connection, &reply, &realloced);
if(retval != UA_STATUSCODE_GOOD) {
UA_LOG_INFO(client->config.logger, UA_LOGCATEGORY_NETWORK, "Receiving ACK message failed");
return retval;
}
} while(reply.length == 0);
offset = 0;
UA_TcpMessageHeader_decodeBinary(&reply, &offset, &messageHeader);
UA_TcpAcknowledgeMessage ackMessage;
retval = UA_TcpAcknowledgeMessage_decodeBinary(&reply, &offset, &ackMessage);
if(!realloced)
client->connection.releaseRecvBuffer(&client->connection, &reply);
else
UA_ByteString_deleteMembers(&reply);
if(retval != UA_STATUSCODE_GOOD) {
UA_LOG_INFO(client->config.logger, UA_LOGCATEGORY_NETWORK, "Decoding ACK message failed");
return retval;
}
UA_LOG_DEBUG(client->config.logger, UA_LOGCATEGORY_NETWORK, "Received ACK message");
conn->remoteConf.maxChunkCount = ackMessage.maxChunkCount;
conn->remoteConf.maxMessageSize = ackMessage.maxMessageSize;
conn->remoteConf.protocolVersion = ackMessage.protocolVersion;
conn->remoteConf.recvBufferSize = ackMessage.receiveBufferSize;
conn->remoteConf.sendBufferSize = ackMessage.sendBufferSize;
conn->state = UA_CONNECTION_ESTABLISHED;
return UA_STATUSCODE_GOOD;
}
static UA_StatusCode SecureChannelHandshake(UA_Client *client, UA_Boolean renew) {
/* Check if sc is still valid */
if(renew && client->scRenewAt - UA_DateTime_now() > 0)
return UA_STATUSCODE_GOOD;
UA_Connection *c = &client->connection;
if(c->state != UA_CONNECTION_ESTABLISHED)
return UA_STATUSCODE_BADSERVERNOTCONNECTED;
UA_SecureConversationMessageHeader messageHeader;
messageHeader.messageHeader.messageTypeAndChunkType = UA_MESSAGETYPE_OPN + UA_CHUNKTYPE_FINAL;
if(renew){
messageHeader.secureChannelId = client->channel.securityToken.channelId;
}else{
messageHeader.secureChannelId = 0;
}
UA_SequenceHeader seqHeader;
seqHeader.sequenceNumber = ++client->channel.sequenceNumber;
seqHeader.requestId = ++client->requestId;
UA_AsymmetricAlgorithmSecurityHeader asymHeader;
UA_AsymmetricAlgorithmSecurityHeader_init(&asymHeader);
asymHeader.securityPolicyUri = UA_STRING_ALLOC("http://opcfoundation.org/UA/SecurityPolicy#None");
/* id of opensecurechannelrequest */
UA_NodeId requestType = UA_NODEID_NUMERIC(0, UA_NS0ID_OPENSECURECHANNELREQUEST + UA_ENCODINGOFFSET_BINARY);
UA_OpenSecureChannelRequest opnSecRq;
UA_OpenSecureChannelRequest_init(&opnSecRq);
opnSecRq.requestHeader.timestamp = UA_DateTime_now();
opnSecRq.requestHeader.authenticationToken = client->authenticationToken;
opnSecRq.requestedLifetime = client->config.secureChannelLifeTime;
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");
}
UA_ByteString_copy(&client->channel.clientNonce, &opnSecRq.clientNonce);
opnSecRq.securityMode = UA_MESSAGESECURITYMODE_NONE;
UA_ByteString message;
UA_StatusCode retval = c->getSendBuffer(c, c->remoteConf.recvBufferSize, &message);
if(retval != UA_STATUSCODE_GOOD) {
UA_AsymmetricAlgorithmSecurityHeader_deleteMembers(&asymHeader);
UA_OpenSecureChannelRequest_deleteMembers(&opnSecRq);
return retval;
}
size_t offset = 12;
retval = UA_AsymmetricAlgorithmSecurityHeader_encodeBinary(&asymHeader, &message, &offset);
retval |= UA_SequenceHeader_encodeBinary(&seqHeader, &message, &offset);
retval |= UA_NodeId_encodeBinary(&requestType, &message, &offset);
retval |= UA_OpenSecureChannelRequest_encodeBinary(&opnSecRq, &message, &offset);
messageHeader.messageHeader.messageSize = (UA_UInt32)offset;
offset = 0;
retval |= UA_SecureConversationMessageHeader_encodeBinary(&messageHeader, &message, &offset);
UA_AsymmetricAlgorithmSecurityHeader_deleteMembers(&asymHeader);
UA_OpenSecureChannelRequest_deleteMembers(&opnSecRq);
if(retval != UA_STATUSCODE_GOOD) {
client->connection.releaseSendBuffer(&client->connection, &message);
return retval;
}
message.length = messageHeader.messageHeader.messageSize;
retval = client->connection.send(&client->connection, &message);
if(retval != UA_STATUSCODE_GOOD)
return retval;
UA_ByteString reply;
UA_ByteString_init(&reply);
UA_Boolean realloced = false;
do {
retval = c->recv(c, &reply, client->config.timeout);
retval |= UA_Connection_completeMessages(c, &reply, &realloced);
if(retval != UA_STATUSCODE_GOOD) {
UA_LOG_DEBUG(client->config.logger, UA_LOGCATEGORY_SECURECHANNEL,
"Receiving OpenSecureChannelResponse failed");
return retval;
}
} while(reply.length == 0);
offset = 0;
UA_SecureConversationMessageHeader_decodeBinary(&reply, &offset, &messageHeader);
UA_AsymmetricAlgorithmSecurityHeader_decodeBinary(&reply, &offset, &asymHeader);
UA_SequenceHeader_decodeBinary(&reply, &offset, &seqHeader);
UA_NodeId_decodeBinary(&reply, &offset, &requestType);
UA_NodeId expectedRequest = UA_NODEID_NUMERIC(0, UA_NS0ID_OPENSECURECHANNELRESPONSE +
UA_ENCODINGOFFSET_BINARY);
if(!UA_NodeId_equal(&requestType, &expectedRequest)) {
UA_ByteString_deleteMembers(&reply);
UA_AsymmetricAlgorithmSecurityHeader_deleteMembers(&asymHeader);
UA_NodeId_deleteMembers(&requestType);
UA_LOG_DEBUG(client->config.logger, UA_LOGCATEGORY_CLIENT,
"Reply answers the wrong request. Expected OpenSecureChannelResponse.");
return UA_STATUSCODE_BADINTERNALERROR;
}
UA_OpenSecureChannelResponse response;
UA_OpenSecureChannelResponse_init(&response);
retval = UA_OpenSecureChannelResponse_decodeBinary(&reply, &offset, &response);
if(!realloced)
c->releaseRecvBuffer(c, &reply);
else
UA_ByteString_deleteMembers(&reply);
if(retval != UA_STATUSCODE_GOOD) {
UA_LOG_DEBUG(client->config.logger, UA_LOGCATEGORY_SECURECHANNEL, "Decoding OpenSecureChannelResponse failed");
UA_AsymmetricAlgorithmSecurityHeader_deleteMembers(&asymHeader);
UA_OpenSecureChannelResponse_init(&response);
response.responseHeader.serviceResult = retval;
return retval;
}
//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->scRenewAt = UA_DateTime_now() +
(UA_DateTime)(response.securityToken.revisedLifetime * (UA_Double)UA_MSEC_TO_DATETIME * 0.75);
retval = response.responseHeader.serviceResult;
if(retval != UA_STATUSCODE_GOOD)
UA_LOG_DEBUG(client->config.logger, UA_LOGCATEGORY_SECURECHANNEL, "SecureChannel could not be opened / renewed");
else {
UA_ChannelSecurityToken_deleteMembers(&client->channel.securityToken);
UA_ChannelSecurityToken_copy(&response.securityToken, &client->channel.securityToken);
/* if the handshake is repeated, replace the old nonce */
UA_ByteString_deleteMembers(&client->channel.serverNonce);
UA_ByteString_copy(&response.serverNonce, &client->channel.serverNonce);
if(renew)
UA_LOG_DEBUG(client->config.logger, UA_LOGCATEGORY_SECURECHANNEL, "SecureChannel renewed");
else
UA_LOG_DEBUG(client->config.logger, UA_LOGCATEGORY_SECURECHANNEL, "SecureChannel opened");
}
UA_OpenSecureChannelResponse_deleteMembers(&response);
UA_AsymmetricAlgorithmSecurityHeader_deleteMembers(&asymHeader);
return retval;
}
static UA_StatusCode ActivateSession(UA_Client *client) {
UA_ActivateSessionRequest request;
UA_ActivateSessionRequest_init(&request);
request.requestHeader.requestHandle = 2; //TODO: is it a magic number?
request.requestHeader.authenticationToken = client->authenticationToken;
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_malloc(sizeof(UA_AnonymousIdentityToken));
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_malloc(sizeof(UA_UserNameIdentityToken));
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]);
UA_ActivateSessionRequest_deleteMembers(&request);
UA_ActivateSessionResponse_deleteMembers(&response);
return response.responseHeader.serviceResult; // not deleted
}
/**
* Gets a list of endpoints
* Memory is allocated for endpointDescription array
*/
static UA_StatusCode
GetEndpoints(UA_Client *client, size_t* endpointDescriptionsSize, UA_EndpointDescription** endpointDescriptions) {
UA_GetEndpointsRequest request;
UA_GetEndpointsRequest_init(&request);
request.requestHeader.authenticationToken = client->authenticationToken;
request.requestHeader.timestamp = UA_DateTime_now();
request.requestHeader.timeoutHint = 10000;
request.endpointUrl = client->endpointUrl; // assume the endpointurl outlives the service call
UA_GetEndpointsResponse response;
UA_GetEndpointsResponse_init(&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_LOG_ERROR(client->config.logger, UA_LOGCATEGORY_CLIENT, "GetEndpointRequest failed");
UA_GetEndpointsResponse_deleteMembers(&response);
return response.responseHeader.serviceResult;
}
*endpointDescriptionsSize = response.endpointsSize;
*endpointDescriptions = UA_Array_new(response.endpointsSize, &UA_TYPES[UA_TYPES_ENDPOINTDESCRIPTION]);
for(size_t i=0;i<response.endpointsSize;i++)
UA_EndpointDescription_copy(&response.endpoints[i], &(*endpointDescriptions)[i]);
UA_GetEndpointsResponse_deleteMembers(&response);
return UA_STATUSCODE_GOOD;
}
static UA_StatusCode EndpointsHandshake(UA_Client *client) {
UA_EndpointDescription* endpointArray = NULL;
size_t endpointArraySize = 0;
UA_StatusCode retval = GetEndpoints(client, &endpointArraySize, &endpointArray);
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 */
//NODE: 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;
endpointFound = true;
/* endpoint with no security found */
/* 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];
//anonymous authentication
if(client->authenticationMethod == UA_CLIENTAUTHENTICATION_NONE){
if(userToken->tokenType != UA_USERTOKENTYPE_ANONYMOUS)
continue;
}else{
//username authentication
if(userToken->tokenType != UA_USERTOKENTYPE_USERNAME)
continue;
}
tokenFound = true;
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");
return UA_STATUSCODE_BADINTERNALERROR;
}
if(!tokenFound) {
UA_LOG_ERROR(client->config.logger, UA_LOGCATEGORY_CLIENT, "No anonymous token found");
return UA_STATUSCODE_BADINTERNALERROR;
}
return retval;
}
static UA_StatusCode SessionHandshake(UA_Client *client) {
UA_CreateSessionRequest request;
UA_CreateSessionRequest_init(&request);
// todo: is this needed for all requests?
UA_NodeId_copy(&client->authenticationToken, &request.requestHeader.authenticationToken);
request.requestHeader.timestamp = UA_DateTime_now();
request.requestHeader.timeoutHint = 10000;
UA_ByteString_copy(&client->channel.clientNonce, &request.clientNonce);
request.requestedSessionTimeout = 1200000;
request.maxResponseMessageSize = UA_INT32_MAX;
UA_CreateSessionResponse response;
UA_CreateSessionResponse_init(&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_CreateSessionRequest_deleteMembers(&request);
UA_CreateSessionResponse_deleteMembers(&response);
return response.responseHeader.serviceResult; // not deleted
}
static UA_StatusCode CloseSession(UA_Client *client) {
UA_CloseSessionRequest request;
UA_CloseSessionRequest_init(&request);
request.requestHeader.timestamp = UA_DateTime_now();
request.requestHeader.timeoutHint = 10000;
request.deleteSubscriptions = true;
UA_NodeId_copy(&client->authenticationToken, &request.requestHeader.authenticationToken);
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);
return response.responseHeader.serviceResult; // not deleted
}
static UA_StatusCode CloseSecureChannel(UA_Client *client) {
UA_SecureChannel *channel = &client->channel;
UA_CloseSecureChannelRequest request;
UA_CloseSecureChannelRequest_init(&request);
request.requestHeader.requestHandle = 1; //TODO: magic number?
request.requestHeader.timestamp = UA_DateTime_now();
request.requestHeader.timeoutHint = 10000;
request.requestHeader.authenticationToken = client->authenticationToken;
UA_SecureConversationMessageHeader msgHeader;
msgHeader.messageHeader.messageTypeAndChunkType = UA_MESSAGETYPE_CLO + UA_CHUNKTYPE_FINAL;
msgHeader.secureChannelId = client->channel.securityToken.channelId;
UA_SymmetricAlgorithmSecurityHeader symHeader;
symHeader.tokenId = channel->securityToken.tokenId;
UA_SequenceHeader seqHeader;
seqHeader.sequenceNumber = ++channel->sequenceNumber;
seqHeader.requestId = ++client->requestId;
UA_NodeId typeId = UA_NODEID_NUMERIC(0, UA_NS0ID_CLOSESECURECHANNELREQUEST + UA_ENCODINGOFFSET_BINARY);
UA_ByteString message;
UA_Connection *c = &client->connection;
UA_StatusCode retval = c->getSendBuffer(c, c->remoteConf.recvBufferSize, &message);
if(retval != UA_STATUSCODE_GOOD)
return retval;
size_t offset = 12;
retval |= UA_SymmetricAlgorithmSecurityHeader_encodeBinary(&symHeader, &message, &offset);
retval |= UA_SequenceHeader_encodeBinary(&seqHeader, &message, &offset);
retval |= UA_NodeId_encodeBinary(&typeId, &message, &offset);
retval |= UA_encodeBinary(&request, &UA_TYPES[UA_TYPES_CLOSESECURECHANNELREQUEST],NULL,NULL, &message, &offset);
msgHeader.messageHeader.messageSize = (UA_UInt32)offset;
offset = 0;
retval |= UA_SecureConversationMessageHeader_encodeBinary(&msgHeader, &message, &offset);
if(retval != UA_STATUSCODE_GOOD) {
client->connection.releaseSendBuffer(&client->connection, &message);
return retval;
}
message.length = msgHeader.messageHeader.messageSize;
retval = client->connection.send(&client->connection, &message);
return retval;
}
UA_StatusCode
UA_Client_getEndpoints(UA_Client *client, const char *serverUrl,
size_t* endpointDescriptionsSize,
UA_EndpointDescription** endpointDescriptions) {
if(client->state == UA_CLIENTSTATE_CONNECTED)
return UA_STATUSCODE_GOOD;
if(client->state == UA_CLIENTSTATE_ERRORED)
UA_Client_reset(client);
UA_StatusCode retval = UA_STATUSCODE_GOOD;
client->connection = client->config.connectionFunc(UA_ConnectionConfig_standard, serverUrl, client->config.logger);
if(client->connection.state != UA_CONNECTION_OPENING) {
retval = UA_STATUSCODE_BADCONNECTIONCLOSED;
goto cleanup;
}
client->endpointUrl = UA_STRING_ALLOC(serverUrl);
if(!client->endpointUrl.data) {
retval = UA_STATUSCODE_BADOUTOFMEMORY;
goto cleanup;
}
client->connection.localConf = client->config.localConnectionConfig;
retval = HelAckHandshake(client);
if(retval == UA_STATUSCODE_GOOD)
retval = SecureChannelHandshake(client, false);
if(retval == UA_STATUSCODE_GOOD)
retval = GetEndpoints(client, endpointDescriptionsSize, endpointDescriptions);
/* always cleanup */
cleanup:
UA_Client_reset(client);
return retval;
}
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_connect(UA_Client *client, const char *endpointUrl) {
if(client->state == UA_CLIENTSTATE_CONNECTED)
return UA_STATUSCODE_GOOD;
if(client->state == UA_CLIENTSTATE_ERRORED) {
UA_Client_reset(client);
}
UA_StatusCode retval = UA_STATUSCODE_GOOD;
client->connection = client->config.connectionFunc(UA_ConnectionConfig_standard, endpointUrl, client->config.logger);
if(client->connection.state != UA_CONNECTION_OPENING) {
retval = UA_STATUSCODE_BADCONNECTIONCLOSED;
goto cleanup;
}
client->endpointUrl = UA_STRING_ALLOC(endpointUrl);
if(!client->endpointUrl.data) {
retval = UA_STATUSCODE_BADOUTOFMEMORY;
goto cleanup;
}
client->connection.localConf = client->config.localConnectionConfig;
retval = HelAckHandshake(client);
if(retval == UA_STATUSCODE_GOOD)
retval = SecureChannelHandshake(client, false);
if(retval == UA_STATUSCODE_GOOD)
retval = EndpointsHandshake(client);
if(retval == UA_STATUSCODE_GOOD)
retval = SessionHandshake(client);
if(retval == UA_STATUSCODE_GOOD)
retval = ActivateSession(client);
if(retval == UA_STATUSCODE_GOOD) {
client->connection.state = UA_CONNECTION_ESTABLISHED;
client->state = UA_CLIENTSTATE_CONNECTED;
} else {
goto cleanup;
}
return retval;
cleanup:
UA_Client_reset(client);
return retval;
}
UA_StatusCode UA_Client_disconnect(UA_Client *client) {
UA_StatusCode retval = UA_STATUSCODE_GOOD;
//is a session established?
if(client->state == UA_CLIENTSTATE_CONNECTED && client->channel.connection->state == UA_CONNECTION_ESTABLISHED)
retval = CloseSession(client);
//is a secure channel established?
if(retval == UA_STATUSCODE_GOOD && client->channel.connection->state == UA_CONNECTION_ESTABLISHED)
retval = CloseSecureChannel(client);
return retval;
}
UA_StatusCode UA_Client_manuallyRenewSecureChannel(UA_Client *client) {
UA_StatusCode retval = SecureChannelHandshake(client, true);
if(retval == UA_STATUSCODE_GOOD)
client->state = UA_CLIENTSTATE_CONNECTED;
return retval;
}
/****************/
/* Raw Services */
/****************/
void __UA_Client_Service(UA_Client *client, const void *r, const UA_DataType *requestType,
void *response, const UA_DataType *responseType) {
/* Requests always begin witih a RequestHeader, therefore we can cast. */
UA_RequestHeader *request = (void*)(uintptr_t)r;
UA_StatusCode retval = UA_STATUSCODE_GOOD;
UA_init(response, responseType);
UA_ResponseHeader *respHeader = (UA_ResponseHeader*)response;
/* make sure we have a valid session */
retval = UA_Client_manuallyRenewSecureChannel(client);
if(retval != UA_STATUSCODE_GOOD) {
respHeader->serviceResult = retval;
client->state = UA_CLIENTSTATE_ERRORED;
return;
}
/* handling request parameters */
UA_NodeId_copy(&client->authenticationToken, &request->authenticationToken);
request->timestamp = UA_DateTime_now();
request->requestHandle = ++client->requestHandle;
/* Send the request */
UA_UInt32 requestId = ++client->requestId;
UA_LOG_DEBUG(client->config.logger, UA_LOGCATEGORY_CLIENT,
"Sending a request of type %i", requestType->typeId.identifier.numeric);
retval = UA_SecureChannel_sendBinaryMessage(&client->channel, requestId, request, requestType);
if(retval != UA_STATUSCODE_GOOD) {
if(retval == UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED)
respHeader->serviceResult = UA_STATUSCODE_BADREQUESTTOOLARGE;
else
respHeader->serviceResult = retval;
client->state = UA_CLIENTSTATE_ERRORED;
return;
}
/* Retrieve the response */
// Todo: push this into the generic securechannel implementation for client and server
UA_ByteString reply;
UA_ByteString_init(&reply);
UA_Boolean realloced = false;
do {
retval = client->connection.recv(&client->connection, &reply, client->config.timeout);
retval |= UA_Connection_completeMessages(&client->connection, &reply, &realloced);
if(retval != UA_STATUSCODE_GOOD) {
respHeader->serviceResult = retval;
client->state = UA_CLIENTSTATE_ERRORED;
return;
}
} while(!reply.data);
size_t offset = 0;
UA_SecureConversationMessageHeader msgHeader;
retval |= UA_SecureConversationMessageHeader_decodeBinary(&reply, &offset, &msgHeader);
UA_SymmetricAlgorithmSecurityHeader symHeader;
retval |= UA_SymmetricAlgorithmSecurityHeader_decodeBinary(&reply, &offset, &symHeader);
UA_SequenceHeader seqHeader;
retval |= UA_SequenceHeader_decodeBinary(&reply, &offset, &seqHeader);
UA_NodeId responseId;
retval |= UA_NodeId_decodeBinary(&reply, &offset, &responseId);
UA_NodeId expectedNodeId = UA_NODEID_NUMERIC(0, responseType->typeId.identifier.numeric +
UA_ENCODINGOFFSET_BINARY);
if(retval != UA_STATUSCODE_GOOD)
goto finish;
/* Todo: we need to demux responses since a publish responses may come at any time */
if(!UA_NodeId_equal(&responseId, &expectedNodeId) || seqHeader.requestId != requestId) {
if(responseId.identifier.numeric != UA_NS0ID_SERVICEFAULT + UA_ENCODINGOFFSET_BINARY) {
UA_LOG_ERROR(client->config.logger, UA_LOGCATEGORY_CLIENT,
"Reply answers the wrong request. Expected ns=%i,i=%i. But retrieved ns=%i,i=%i",
expectedNodeId.namespaceIndex, expectedNodeId.identifier.numeric,
responseId.namespaceIndex, responseId.identifier.numeric);
respHeader->serviceResult = UA_STATUSCODE_BADINTERNALERROR;
} else
retval = UA_decodeBinary(&reply, &offset, respHeader, &UA_TYPES[UA_TYPES_SERVICEFAULT]);
goto finish;
}
retval = UA_decodeBinary(&reply, &offset, response, responseType);
if(retval == UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED)
retval = UA_STATUSCODE_BADRESPONSETOOLARGE;
finish:
UA_SymmetricAlgorithmSecurityHeader_deleteMembers(&symHeader);
if(!realloced)
client->connection.releaseRecvBuffer(&client->connection, &reply);
else
UA_ByteString_deleteMembers(&reply);
if(retval != UA_STATUSCODE_GOOD){
UA_LOG_INFO(client->config.logger, UA_LOGCATEGORY_CLIENT, "Error receiving the response");
client->state = UA_CLIENTSTATE_FAULTED;
respHeader->serviceResult = retval;
} else {
client->state = UA_CLIENTSTATE_CONNECTED;
}
UA_LOG_DEBUG(client->config.logger, UA_LOGCATEGORY_CLIENT,
"Received a response of type %i", responseId.identifier.numeric);
}
/*********************************** amalgamated original file "/home/wn/Sources/open62541-open62541-395ce48/src/client/ua_client_highlevel.c" ***********************************/
UA_StatusCode
UA_Client_NamespaceGetIndex(UA_Client *client, UA_String *namespaceUri, UA_UInt16 *namespaceIndex) {
UA_ReadRequest request;
UA_ReadRequest_init(&request);
UA_ReadValueId 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 = 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_StatusCode retval = UA_STATUSCODE_GOOD;
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);
if(bResp.responseHeader.serviceResult == 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);
}
}
}
else
retval = bResp.responseHeader.serviceResult;
UA_BrowseRequest_deleteMembers(&bReq);
UA_BrowseResponse_deleteMembers(&bResp);
return retval;
}
/*******************/
/* Node Management */
/*******************/
UA_StatusCode UA_EXPORT
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_EXPORT
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_StatusCode retval = UA_STATUSCODE_GOOD;
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);
if(response.responseHeader.serviceResult != UA_STATUSCODE_GOOD) {
retval = response.responseHeader.serviceResult;
UA_AddNodesResponse_deleteMembers(&response);
return retval;
}
if(response.resultsSize != 1) {
UA_AddNodesResponse_deleteMembers(&response);
return UA_STATUSCODE_BADUNEXPECTEDERROR;
}
if(outNewNodeId && response.results[0].statusCode == UA_STATUSCODE_GOOD) {
*outNewNodeId = response.results[0].addedNodeId;
UA_NodeId_init(&response.results[0].addedNodeId);
}
retval = response.results[0].statusCode;
UA_AddNodesResponse_deleteMembers(&response);
return retval;
}
/********/
/* Call */
/********/
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) {
UA_CallRequest request;
UA_CallRequest_init(&request);
UA_CallMethodRequest item;
UA_CallMethodRequest_init(&item);
item.methodId = methodId;
item.objectId = objectId;
item.inputArguments = (void*)(uintptr_t)input; // cast const...
item.inputArgumentsSize = inputSize;
request.methodsToCall = &item;
request.methodsToCallSize = 1;
UA_CallResponse response = UA_Client_Service_call(client, request);
UA_StatusCode retval = response.responseHeader.serviceResult;
if(retval != UA_STATUSCODE_GOOD) {
UA_CallResponse_deleteMembers(&response);
return retval;
}
if(response.resultsSize != 1) {
UA_CallResponse_deleteMembers(&response);
return UA_STATUSCODE_BADUNEXPECTEDERROR;
}
retval = response.results[0].statusCode;
if(retval == UA_STATUSCODE_GOOD && response.resultsSize > 0) {
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;
}
/********************/
/* 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
UA_Variant_setScalar(&wValue.value.value, (void*)(uintptr_t)in, inDataType); /* hack. is never written into. */
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;
UA_WriteResponse_deleteMembers(&wResp);
return retval;
}
UA_StatusCode
UA_Client_writeArrayDimensionsAttribute(UA_Client *client, const UA_NodeId nodeId,
const UA_Int32 *newArrayDimensions, size_t newArrayDimensionsSize) {
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_INT32]);
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;
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 && response.resultsSize != 1)
retval = UA_STATUSCODE_BADUNEXPECTEDERROR;
if(retval != UA_STATUSCODE_GOOD) {
UA_ReadResponse_deleteMembers(&response);
return retval;
}
UA_DataValue *res = response.results;
if(res->hasStatus != UA_STATUSCODE_GOOD)
retval = res->hasStatus;
else if(!res->hasValue || !UA_Variant_isScalar(&res->value))
retval = UA_STATUSCODE_BADUNEXPECTEDERROR;
if(retval != UA_STATUSCODE_GOOD) {
UA_ReadResponse_deleteMembers(&response);
return retval;
}
if(attributeId == UA_ATTRIBUTEID_VALUE) {
memcpy(out, &res->value, sizeof(UA_Variant));
UA_Variant_init(&res->value);
} 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;
}
UA_StatusCode
UA_Client_readArrayDimensionsAttribute(UA_Client *client, const UA_NodeId nodeId,
UA_Int32 **outArrayDimensions, size_t *outArrayDimensionsSize) {
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 = response.responseHeader.serviceResult;
if(retval == UA_STATUSCODE_GOOD && response.resultsSize != 1)
retval = UA_STATUSCODE_BADUNEXPECTEDERROR;
if(retval != UA_STATUSCODE_GOOD)
goto cleanup;
UA_DataValue *res = response.results;
if(res->hasStatus != UA_STATUSCODE_GOOD)
retval = res->hasStatus;
else if(!res->hasValue || UA_Variant_isScalar(&res->value))
retval = UA_STATUSCODE_BADUNEXPECTEDERROR;
if(retval != UA_STATUSCODE_GOOD)
goto cleanup;
if(UA_Variant_isScalar(&res->value) ||
res->value.type != &UA_TYPES[UA_TYPES_INT32]) {
retval = UA_STATUSCODE_BADUNEXPECTEDERROR;
goto cleanup;
}
*outArrayDimensions = res->value.data;
*outArrayDimensionsSize = res->value.arrayLength;
UA_free(res->value.data);
res->value.data = NULL;
res->value.arrayLength = 0;
cleanup:
UA_ReadResponse_deleteMembers(&response);
return retval;
}
/*********************************** amalgamated original file "/home/wn/Sources/open62541-open62541-395ce48/src/server/ua_nodestore.c" ***********************************/
#ifndef UA_ENABLE_MULTITHREADING /* conditional compilation */
#define UA_NODESTORE_MINSIZE 64
typedef struct UA_NodeStoreEntry {
struct UA_NodeStoreEntry *orig; // the version this is a copy from (or NULL)
UA_Node node;
} UA_NodeStoreEntry;
struct UA_NodeStore {
UA_NodeStoreEntry **entries;
UA_UInt32 size;
UA_UInt32 count;
UA_UInt32 sizePrimeIndex;
};
/* 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 hash_t 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_UInt16 higher_prime_index(hash_t n) {
UA_UInt16 low = 0;
UA_UInt16 high = (UA_UInt16)(sizeof(primes) / sizeof(hash_t));
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;
}
static UA_NodeStoreEntry * instantiateEntry(UA_NodeClass nodeClass) {
size_t size = sizeof(UA_NodeStoreEntry) - 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_NodeStoreEntry *entry = UA_calloc(1, size);
if(!entry)
return NULL;
entry->node.nodeClass = nodeClass;
return entry;
}
static void deleteEntry(UA_NodeStoreEntry *entry) {
UA_Node_deleteMembersAnyNodeClass(&entry->node);
UA_free(entry);
}
/* Returns true if an entry was found under the nodeid. Otherwise, returns
false and sets slot to a pointer to the next free slot. */
static UA_Boolean
containsNodeId(const UA_NodeStore *ns, const UA_NodeId *nodeid, UA_NodeStoreEntry ***entry) {
hash_t h = hash(nodeid);
UA_UInt32 size = ns->size;
hash_t idx = mod(h, size);
UA_NodeStoreEntry *e = ns->entries[idx];
if(!e) {
*entry = &ns->entries[idx];
return false;
}
if(UA_NodeId_equal(&e->node.nodeId, nodeid)) {
*entry = &ns->entries[idx];
return true;
}
hash_t hash2 = mod2(h, size);
for(;;) {
idx += hash2;
if(idx >= size)
idx -= size;
e = ns->entries[idx];
if(!e) {
*entry = &ns->entries[idx];
return false;
}
if(UA_NodeId_equal(&e->node.nodeId, nodeid)) {
*entry = &ns->entries[idx];
return true;
}
}
/* NOTREACHED */
return true;
}
/* The occupancy of the table after the call will be about 50% */
static UA_StatusCode expand(UA_NodeStore *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_NODESTORE_MINSIZE))
return UA_STATUSCODE_GOOD;
UA_NodeStoreEntry **oentries = ns->entries;
UA_UInt32 nindex = higher_prime_index(count * 2);
UA_UInt32 nsize = primes[nindex];
UA_NodeStoreEntry **nentries;
if(!(nentries = UA_calloc(nsize, sizeof(UA_NodeStoreEntry*))))
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])
continue;
UA_NodeStoreEntry **e;
containsNodeId(ns, &oentries[i]->node.nodeId, &e); /* We know this returns an empty entry here */
*e = oentries[i];
j++;
}
UA_free(oentries);
return UA_STATUSCODE_GOOD;
}
/**********************/
/* Exported functions */
/**********************/
UA_NodeStore * UA_NodeStore_new(void) {
UA_NodeStore *ns;
if(!(ns = UA_malloc(sizeof(UA_NodeStore))))
return NULL;
ns->sizePrimeIndex = higher_prime_index(UA_NODESTORE_MINSIZE);
ns->size = primes[ns->sizePrimeIndex];
ns->count = 0;
if(!(ns->entries = UA_calloc(ns->size, sizeof(UA_NodeStoreEntry*)))) {
UA_free(ns);
return NULL;
}
return ns;
}
void UA_NodeStore_delete(UA_NodeStore *ns) {
UA_UInt32 size = ns->size;
UA_NodeStoreEntry **entries = ns->entries;
for(UA_UInt32 i = 0; i < size; i++) {
if(entries[i])
deleteEntry(entries[i]);
}
UA_free(ns->entries);
UA_free(ns);
}
UA_Node * UA_NodeStore_newNode(UA_NodeClass class) {
UA_NodeStoreEntry *entry = instantiateEntry(class);
if(!entry)
return NULL;
return (UA_Node*)&entry->node;
}
void UA_NodeStore_deleteNode(UA_Node *node) {
deleteEntry(container_of(node, UA_NodeStoreEntry, node));
}
UA_StatusCode UA_NodeStore_insert(UA_NodeStore *ns, UA_Node *node) {
if(ns->size * 3 <= ns->count * 4) {
if(expand(ns) != UA_STATUSCODE_GOOD)
return UA_STATUSCODE_BADINTERNALERROR;
}
UA_NodeId tempNodeid;
tempNodeid = node->nodeId;
tempNodeid.namespaceIndex = 0;
UA_NodeStoreEntry **entry;
if(UA_NodeId_isNull(&tempNodeid)) {
if(node->nodeId.namespaceIndex == 0)
node->nodeId.namespaceIndex = 1;
/* find a free nodeid */
UA_UInt32 identifier = ns->count+1; // start value
UA_UInt32 size = ns->size;
hash_t increase = mod2(identifier, size);
while(true) {
node->nodeId.identifier.numeric = identifier;
if(!containsNodeId(ns, &node->nodeId, &entry))
break;
identifier += increase;
if(identifier >= size)
identifier -= size;
}
} else {
if(containsNodeId(ns, &node->nodeId, &entry)) {
deleteEntry(container_of(node, UA_NodeStoreEntry, node));
return UA_STATUSCODE_BADNODEIDEXISTS;
}
}
*entry = container_of(node, UA_NodeStoreEntry, node);
ns->count++;
return UA_STATUSCODE_GOOD;
}
UA_StatusCode
UA_NodeStore_replace(UA_NodeStore *ns, UA_Node *node) {
UA_NodeStoreEntry **entry;
if(!containsNodeId(ns, &node->nodeId, &entry))
return UA_STATUSCODE_BADNODEIDUNKNOWN;
UA_NodeStoreEntry *newEntry = container_of(node, UA_NodeStoreEntry, node);
if(*entry != newEntry->orig) {
deleteEntry(newEntry);
return UA_STATUSCODE_BADINTERNALERROR; // the node was replaced since the copy was made
}
deleteEntry(*entry);
*entry = newEntry;
return UA_STATUSCODE_GOOD;
}
const UA_Node * UA_NodeStore_get(UA_NodeStore *ns, const UA_NodeId *nodeid) {
UA_NodeStoreEntry **entry;
if(!containsNodeId(ns, nodeid, &entry))
return NULL;
return (const UA_Node*)&(*entry)->node;
}
UA_Node * UA_NodeStore_getCopy(UA_NodeStore *ns, const UA_NodeId *nodeid) {
UA_NodeStoreEntry **slot;
if(!containsNodeId(ns, nodeid, &slot))
return NULL;
UA_NodeStoreEntry *entry = *slot;
UA_NodeStoreEntry *new = instantiateEntry(entry->node.nodeClass);
if(!new)
return NULL;
if(UA_Node_copyAnyNodeClass(&entry->node, &new->node) != UA_STATUSCODE_GOOD) {
deleteEntry(new);
return NULL;
}
new->orig = entry;
return &new->node;
}
UA_StatusCode UA_NodeStore_remove(UA_NodeStore *ns, const UA_NodeId *nodeid) {
UA_NodeStoreEntry **slot;
if(!containsNodeId(ns, nodeid, &slot))
return UA_STATUSCODE_BADNODEIDUNKNOWN;
deleteEntry(*slot);
*slot = NULL;
ns->count--;
/* Downsize the hashmap if it is very empty */
if(ns->count * 8 < ns->size && ns->size > 32)
expand(ns); // this can fail. we just continue with the bigger hashmap.
return UA_STATUSCODE_GOOD;
}
void UA_NodeStore_iterate(UA_NodeStore *ns, UA_NodeStore_nodeVisitor visitor) {
for(UA_UInt32 i = 0; i < ns->size; i++) {
if(ns->entries[i])
visitor((UA_Node*)&ns->entries[i]->node);
}
}
#endif /* UA_ENABLE_MULTITHREADING */
/*********************************** amalgamated original file "/home/wn/Sources/open62541-open62541-395ce48/src/server/ua_nodestore_concurrent.c" ***********************************/
#ifdef UA_ENABLE_MULTITHREADING /* conditional compilation */
struct nodeEntry {
struct cds_lfht_node htn; ///< Contains the next-ptr for urcu-hashmap
struct rcu_head rcu_head; ///< For call-rcu
struct nodeEntry *orig; //< the version this is a copy from (or NULL)
UA_Node node; ///< Might be cast from any _bigger_ UA_Node* type. Allocate enough memory!
};
static struct nodeEntry * instantiateEntry(UA_NodeClass class) {
size_t size = sizeof(struct nodeEntry) - sizeof(UA_Node);
switch(class) {
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;
}
struct nodeEntry *entry = UA_calloc(1, size);
if(!entry)
return NULL;
entry->node.nodeClass = class;
return entry;
}
static void deleteEntry(struct rcu_head *head) {
struct nodeEntry *entry = container_of(head, struct nodeEntry, rcu_head);
UA_Node_deleteMembersAnyNodeClass(&entry->node);
UA_free(entry);
}
/* We are in a rcu_read lock. So the node will not be freed under our feet. */
static int compare(struct cds_lfht_node *htn, const void *orig) {
const UA_NodeId *origid = (const UA_NodeId *)orig;
/* The htn is first in the entry structure. */
const UA_NodeId *newid = &((struct nodeEntry *)htn)->node.nodeId;
return UA_NodeId_equal(newid, origid);
}
UA_NodeStore * UA_NodeStore_new() {
/* 64 is the minimum size for the hashtable. */
return (UA_NodeStore*)cds_lfht_new(64, 64, 0, CDS_LFHT_AUTO_RESIZE, NULL);
}
/* do not call with read-side critical section held!! */
void UA_NodeStore_delete(UA_NodeStore *ns) {
UA_ASSERT_RCU_LOCKED();
struct cds_lfht *ht = (struct cds_lfht*)ns;
struct cds_lfht_iter iter;
cds_lfht_first(ht, &iter);
while(iter.node) {
if(!cds_lfht_del(ht, iter.node)) {
/* points to the htn entry, which is first */
struct nodeEntry *entry = (struct nodeEntry*) iter.node;
call_rcu(&entry->rcu_head, deleteEntry);
}
cds_lfht_next(ht, &iter);
}
cds_lfht_destroy(ht, NULL);
UA_free(ns);
}
UA_Node * UA_NodeStore_newNode(UA_NodeClass class) {
struct nodeEntry *entry = instantiateEntry(class);
if(!entry)
return NULL;
return (UA_Node*)&entry->node;
}
void UA_NodeStore_deleteNode(UA_Node *node) {
struct nodeEntry *entry = container_of(node, struct nodeEntry, node);
deleteEntry(&entry->rcu_head);
}
UA_StatusCode UA_NodeStore_insert(UA_NodeStore *ns, UA_Node *node) {
UA_ASSERT_RCU_LOCKED();
struct nodeEntry *entry = container_of(node, struct nodeEntry, node);
struct cds_lfht *ht = (struct cds_lfht*)ns;
cds_lfht_node_init(&entry->htn);
struct cds_lfht_node *result;
//namespace index is assumed to be valid
UA_NodeId tempNodeid;
tempNodeid = node->nodeId;
tempNodeid.namespaceIndex = 0;
if(!UA_NodeId_isNull(&tempNodeid)) {
hash_t h = hash(&node->nodeId);
result = cds_lfht_add_unique(ht, h, compare, &node->nodeId, &entry->htn);
/* If the nodeid exists already */
if(result != &entry->htn) {
deleteEntry(&entry->rcu_head);
return UA_STATUSCODE_BADNODEIDEXISTS;
}
} else {
/* create a unique nodeid */
node->nodeId.identifierType = UA_NODEIDTYPE_NUMERIC;
if(node->nodeId.namespaceIndex == 0) // original request for ns=0 should yield ns=1
node->nodeId.namespaceIndex = 1;
unsigned long identifier;
long before, after;
cds_lfht_count_nodes(ht, &before, &identifier, &after); // current number of nodes stored
identifier++;
node->nodeId.identifier.numeric = (UA_UInt32)identifier;
while(true) {
hash_t h = hash(&node->nodeId);
result = cds_lfht_add_unique(ht, h, compare, &node->nodeId, &entry->htn);
if(result == &entry->htn)
break;
node->nodeId.identifier.numeric += (UA_UInt32)(identifier * 2654435761);
}
}
return UA_STATUSCODE_GOOD;
}
UA_StatusCode UA_NodeStore_replace(UA_NodeStore *ns, UA_Node *node) {
UA_ASSERT_RCU_LOCKED();
struct nodeEntry *entry = container_of(node, struct nodeEntry, node);
struct cds_lfht *ht = (struct cds_lfht*)ns;
/* Get the current version */
hash_t h = hash(&node->nodeId);
struct cds_lfht_iter iter;
cds_lfht_lookup(ht, h, compare, &node->nodeId, &iter);
if(!iter.node)
return UA_STATUSCODE_BADNODEIDUNKNOWN;
/* We try to replace an obsolete version of the node */
struct nodeEntry *oldEntry = (struct nodeEntry*)iter.node;
if(oldEntry != entry->orig)
return UA_STATUSCODE_BADINTERNALERROR;
cds_lfht_node_init(&entry->htn);
if(cds_lfht_replace(ht, &iter, h, compare, &node->nodeId, &entry->htn) != 0) {
/* Replacing failed. Maybe the node got replaced just before this thread tried to.*/
deleteEntry(&entry->rcu_head);
return UA_STATUSCODE_BADINTERNALERROR;
}
/* If an entry got replaced, mark it as dead. */
call_rcu(&oldEntry->rcu_head, deleteEntry);
return UA_STATUSCODE_GOOD;
}
UA_StatusCode UA_NodeStore_remove(UA_NodeStore *ns, const UA_NodeId *nodeid) {
UA_ASSERT_RCU_LOCKED();
struct cds_lfht *ht = (struct cds_lfht*)ns;
hash_t h = hash(nodeid);
struct cds_lfht_iter iter;
cds_lfht_lookup(ht, h, compare, nodeid, &iter);
if(!iter.node || cds_lfht_del(ht, iter.node) != 0)
return UA_STATUSCODE_BADNODEIDUNKNOWN;
struct nodeEntry *entry = (struct nodeEntry*)iter.node;
call_rcu(&entry->rcu_head, deleteEntry);
return UA_STATUSCODE_GOOD;
}
const UA_Node * UA_NodeStore_get(UA_NodeStore *ns, const UA_NodeId *nodeid) {
UA_ASSERT_RCU_LOCKED();
struct cds_lfht *ht = (struct cds_lfht*)ns;
hash_t h = hash(nodeid);
struct cds_lfht_iter iter;
cds_lfht_lookup(ht, h, compare, nodeid, &iter);
struct nodeEntry *found_entry = (struct nodeEntry*)iter.node;
if(!found_entry)
return NULL;
return &found_entry->node;
}
UA_Node * UA_NodeStore_getCopy(UA_NodeStore *ns, const UA_NodeId *nodeid) {
UA_ASSERT_RCU_LOCKED();
struct cds_lfht *ht = (struct cds_lfht*)ns;
hash_t h = hash(nodeid);
struct cds_lfht_iter iter;
cds_lfht_lookup(ht, h, compare, nodeid, &iter);
struct nodeEntry *entry = (struct nodeEntry*)iter.node;
if(!entry)
return NULL;
struct nodeEntry *new = instantiateEntry(entry->node.nodeClass);
if(!new)
return NULL;
if(UA_Node_copyAnyNodeClass(&entry->node, &new->node) != UA_STATUSCODE_GOOD) {
deleteEntry(&new->rcu_head);
return NULL;
}
new->orig = entry;
return &new->node;
}
void UA_NodeStore_iterate(UA_NodeStore *ns, UA_NodeStore_nodeVisitor visitor) {
UA_ASSERT_RCU_LOCKED();
struct cds_lfht *ht = (struct cds_lfht*)ns;
struct cds_lfht_iter iter;
cds_lfht_first(ht, &iter);
while(iter.node != NULL) {
struct nodeEntry *found_entry = (struct nodeEntry*)iter.node;
visitor(&found_entry->node);
cds_lfht_next(ht, &iter);
}
}
#endif /* UA_ENABLE_MULTITHREADING */
/*********************************** amalgamated original file "/home/wn/Sources/open62541-open62541-395ce48/src/server/ua_services_call.c" ***********************************/
#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++) {
if(ofMethod->references[i].isInverse == false &&
UA_NodeId_equal(&hasProperty, &ofMethod->references[i].referenceTypeId)) {
const UA_Node *refTarget =
UA_NodeStore_get(server->nodestore, &ofMethod->references[i].targetId.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;
}
}
}
return NULL;
}
static UA_StatusCode
satisfySignature(const UA_Variant *var, const UA_Argument *arg) {
if(!UA_NodeId_equal(&var->type->typeId, &arg->dataType) )
return UA_STATUSCODE_BADINVALIDARGUMENT;
// Note: The namespace compiler will compile nodes with their actual array dimensions
// Todo: Check if this is standard conform for scalars
if(arg->arrayDimensionsSize > 0 && var->arrayDimensionsSize > 0)
if(var->arrayDimensionsSize != arg->arrayDimensionsSize)
return UA_STATUSCODE_BADINVALIDARGUMENT;
UA_Int32 *varDims = var->arrayDimensions;
size_t varDimsSize = var->arrayDimensionsSize;
UA_Boolean scalar = UA_Variant_isScalar(var);
/* The dimension 1 is implicit in the array length */
UA_Int32 fakeDims;
if(!scalar && !varDims) {
fakeDims = (UA_Int32)var->arrayLength;
varDims = &fakeDims;
varDimsSize = 1;
}
/* ValueRank Semantics
* n >= 1: the value is an array with the specified number of dimens*ions.
* n = 0: the value is an array with one or more dimensions.
* n = -1: the value is a scalar.
* n = -2: the value can be a scalar or an array with any number of dimensions.
* n = -3: the value can be a scalar or a one dimensional array. */
switch(arg->valueRank) {
case -3:
if(varDimsSize > 1)
return UA_STATUSCODE_BADINVALIDARGUMENT;
break;
case -2:
break;
case -1:
if(!scalar)
return UA_STATUSCODE_BADINVALIDARGUMENT;
break;
case 0:
if(scalar || !varDims)
return UA_STATUSCODE_BADINVALIDARGUMENT;
break;
default:
break;
}
/* do the array dimensions match? */
if(arg->arrayDimensionsSize != varDimsSize)
return UA_STATUSCODE_BADINVALIDARGUMENT;
for(size_t i = 0; i < varDimsSize; i++) {
if((UA_Int32)arg->arrayDimensions[i] != varDims[i])
return UA_STATUSCODE_BADINVALIDARGUMENT;
}
return UA_STATUSCODE_GOOD;
}
static UA_StatusCode
argConformsToDefinition(const UA_VariableNode *argRequirements, size_t argsSize, const UA_Variant *args) {
if(argRequirements->value.variant.value.type != &UA_TYPES[UA_TYPES_ARGUMENT])
return UA_STATUSCODE_BADINTERNALERROR;
UA_Argument *argReqs = (UA_Argument*)argRequirements->value.variant.value.data;
size_t argReqsSize = argRequirements->value.variant.value.arrayLength;
if(argRequirements->valueSource != UA_VALUESOURCE_VARIANT)
return UA_STATUSCODE_BADINTERNALERROR;
if(UA_Variant_isScalar(&argRequirements->value.variant.value))
argReqsSize = 1;
if(argReqsSize > argsSize)
return UA_STATUSCODE_BADARGUMENTSMISSING;
if(argReqsSize != argsSize)
return UA_STATUSCODE_BADINVALIDARGUMENT;
UA_StatusCode retval = UA_STATUSCODE_GOOD;
for(size_t i = 0; i < argReqsSize; i++)
retval |= satisfySignature(&args[i], &argReqs[i]);
return retval;
}
void
Service_Call_single(UA_Server *server, UA_Session *session, const UA_CallMethodRequest *request,
UA_CallMethodResult *result) {
const UA_MethodNode *methodCalled =
(const UA_MethodNode*)UA_NodeStore_get(server->nodestore, &request->methodId);
if(!methodCalled) {
result->statusCode = UA_STATUSCODE_BADMETHODINVALID;
return;
}
const UA_ObjectNode *withObject =
(const UA_ObjectNode*)UA_NodeStore_get(server->nodestore, &request->objectId);
if(!withObject) {
result->statusCode = UA_STATUSCODE_BADNODEIDINVALID;
return;
}
if(methodCalled->nodeClass != UA_NODECLASS_METHOD) {
result->statusCode = UA_STATUSCODE_BADNODECLASSINVALID;
return;
}
if(withObject->nodeClass != UA_NODECLASS_OBJECT && withObject->nodeClass != UA_NODECLASS_OBJECTTYPE) {
result->statusCode = UA_STATUSCODE_BADNODECLASSINVALID;
return;
}
/* Verify method/object relations */
// Object must have a hasComponent reference (or any inherited referenceType from sayd reference)
// to be valid for a methodCall...
result->statusCode = UA_STATUSCODE_BADMETHODINVALID;
for(size_t i = 0; i < withObject->referencesSize; i++) {
if(withObject->references[i].referenceTypeId.identifier.numeric == UA_NS0ID_HASCOMPONENT) {
// FIXME: Not checking any subtypes of HasComponent at the moment
if(UA_NodeId_equal(&withObject->references[i].targetId.nodeId, &methodCalled->nodeId)) {
result->statusCode = UA_STATUSCODE_GOOD;
break;
}
}
}
if(result->statusCode != UA_STATUSCODE_GOOD)
return;
/* Verify method executable */
if(!methodCalled->executable || !methodCalled->userExecutable) {
result->statusCode = UA_STATUSCODE_BADNOTWRITABLE; // There is no NOTEXECUTABLE?
return;
}
/* Verify Input Argument count, types and sizes */
const UA_VariableNode *inputArguments;
inputArguments = getArgumentsVariableNode(server, methodCalled, UA_STRING("InputArguments"));
if(inputArguments) {
result->statusCode = argConformsToDefinition(inputArguments, request->inputArgumentsSize,
request->inputArguments);
if(result->statusCode != UA_STATUSCODE_GOOD)
return;
} else if(request->inputArgumentsSize > 0) {
result->statusCode = UA_STATUSCODE_BADINVALIDARGUMENT;
return;
}
const UA_VariableNode *outputArguments =
getArgumentsVariableNode(server, methodCalled, UA_STRING("OutputArguments"));
if(!outputArguments) {
// A MethodNode must have an OutputArguments variable (which may be empty)
result->statusCode = UA_STATUSCODE_BADINTERNALERROR;
return;
}
/* Call method if available */
if(methodCalled->attachedMethod) {
result->outputArguments = UA_Array_new(outputArguments->value.variant.value.arrayLength,
&UA_TYPES[UA_TYPES_VARIANT]);
result->outputArgumentsSize = outputArguments->value.variant.value.arrayLength;
result->statusCode = methodCalled->attachedMethod(methodCalled->methodHandle, withObject->nodeId,
request->inputArgumentsSize, request->inputArguments,
result->outputArgumentsSize, result->outputArguments);
}
else
result->statusCode = UA_STATUSCODE_BADNOTWRITABLE; // There is no NOTEXECUTABLE?
/* TODO: Verify Output Argument count, types and sizes */
}
void Service_Call(UA_Server *server, UA_Session *session, const UA_CallRequest *request,
UA_CallResponse *response) {
if(request->methodsToCallSize <= 0) {
response->responseHeader.serviceResult = UA_STATUSCODE_BADNOTHINGTODO;
return;
}
response->results = UA_Array_new(request->methodsToCallSize,
&UA_TYPES[UA_TYPES_CALLMETHODRESULT]);
if(!response->results) {
response->responseHeader.serviceResult = UA_STATUSCODE_BADOUTOFMEMORY;
return;
}
response->resultsSize = request->methodsToCallSize;
for(size_t i = 0; i < request->methodsToCallSize;i++)
Service_Call_single(server, session, &request->methodsToCall[i], &response->results[i]);
}
#endif /* UA_ENABLE_METHODCALLS */
/*********************************** amalgamated original file "/home/wn/Sources/open62541-open62541-395ce48/src/server/ua_subscription.c" ***********************************/
#ifdef UA_ENABLE_SUBSCRIPTIONS /* conditional compilation */
/*****************/
/* MonitoredItem */
/*****************/
UA_MonitoredItem * UA_MonitoredItem_new() {
UA_MonitoredItem *new = UA_malloc(sizeof(UA_MonitoredItem));
new->subscription = NULL;
new->currentQueueSize = 0;
new->maxQueueSize = 0;
new->monitoredItemType = UA_MONITOREDITEMTYPE_CHANGENOTIFY; /* currently hardcoded */
new->timestampsToReturn = UA_TIMESTAMPSTORETURN_SOURCE;
UA_String_init(&new->indexRange);
TAILQ_INIT(&new->queue);
UA_NodeId_init(&new->monitoredNodeId);
new->lastSampledValue = UA_BYTESTRING_NULL;
memset(&new->sampleJobGuid, 0, sizeof(UA_Guid));
new->sampleJobIsRegistered = false;
return new;
}
void MonitoredItem_delete(UA_Server *server, UA_MonitoredItem *monitoredItem) {
MonitoredItem_unregisterSampleJob(server, monitoredItem);
/* clear the queued samples */
MonitoredItem_queuedValue *val, *val_tmp;
TAILQ_FOREACH_SAFE(val, &monitoredItem->queue, listEntry, val_tmp) {
TAILQ_REMOVE(&monitoredItem->queue, val, listEntry);
UA_DataValue_deleteMembers(&val->value);
UA_free(val);
}
monitoredItem->currentQueueSize = 0;
LIST_REMOVE(monitoredItem, listEntry);
UA_String_deleteMembers(&monitoredItem->indexRange);
UA_ByteString_deleteMembers(&monitoredItem->lastSampledValue);
UA_NodeId_deleteMembers(&monitoredItem->monitoredNodeId);
UA_free(monitoredItem);
}
static void SampleCallback(UA_Server *server, UA_MonitoredItem *monitoredItem) {
if(monitoredItem->monitoredItemType != UA_MONITOREDITEMTYPE_CHANGENOTIFY) {
UA_LOG_DEBUG(server->config.logger, UA_LOGCATEGORY_SERVER,
"Cannot process a monitoreditem that is not a data change notification");
return;
}
MonitoredItem_queuedValue *newvalue = UA_malloc(sizeof(MonitoredItem_queuedValue));
if(!newvalue) {
UA_LOG_INFO(server->config.logger, UA_LOGCATEGORY_SERVER,
"Skipped a sample due to lack of memory on monitoreditem %u", monitoredItem->itemId);
return;
}
UA_DataValue_init(&newvalue->value);
newvalue->clientHandle = monitoredItem->clientHandle;
UA_LOG_DEBUG(server->config.logger, UA_LOGCATEGORY_SERVER,
"Sampling the value on monitoreditem %u", monitoredItem->itemId);
/* Read the value */
UA_ReadValueId rvid;
UA_ReadValueId_init(&rvid);
rvid.nodeId = monitoredItem->monitoredNodeId;
rvid.attributeId = monitoredItem->attributeID;
rvid.indexRange = monitoredItem->indexRange;
UA_Subscription *sub = monitoredItem->subscription;
Service_Read_single(server, sub->session, monitoredItem->timestampsToReturn, &rvid, &newvalue->value);
/* encode to see if the data has changed */
size_t binsize = UA_calcSizeBinary(&newvalue->value.value, &UA_TYPES[UA_TYPES_VARIANT]);
UA_ByteString newValueAsByteString;
UA_StatusCode retval = UA_ByteString_allocBuffer(&newValueAsByteString, binsize);
if(retval != UA_STATUSCODE_GOOD) {
UA_DataValue_deleteMembers(&newvalue->value);
UA_free(newvalue);
return;
}
size_t encodingOffset = 0;
retval = UA_encodeBinary(&newvalue->value.value, &UA_TYPES[UA_TYPES_VARIANT],
NULL, NULL, &newValueAsByteString, &encodingOffset);
/* error or the content has not changed */
if(retval != UA_STATUSCODE_GOOD ||
(monitoredItem->lastSampledValue.data &&
UA_String_equal(&newValueAsByteString, &monitoredItem->lastSampledValue))) {
UA_ByteString_deleteMembers(&newValueAsByteString);
UA_DataValue_deleteMembers(&newvalue->value);
UA_free(newvalue);
UA_LOG_DEBUG(server->config.logger, UA_LOGCATEGORY_SERVER,
"Do not sample since the data value has not changed");
return;
}
/* do we have space in the queue? */
if(monitoredItem->currentQueueSize >= monitoredItem->maxQueueSize) {
if(!monitoredItem->discardOldest) {
// We cannot remove the oldest value and theres no queue space left. We're done here.
UA_ByteString_deleteMembers(&newValueAsByteString);
UA_DataValue_deleteMembers(&newvalue->value);
UA_free(newvalue);
return;
}
MonitoredItem_queuedValue *queueItem = TAILQ_LAST(&monitoredItem->queue, QueueOfQueueDataValues);
TAILQ_REMOVE(&monitoredItem->queue, queueItem, listEntry);
UA_DataValue_deleteMembers(&queueItem->value);
UA_free(queueItem);
monitoredItem->currentQueueSize--;
}
/* add the sample */
UA_ByteString_deleteMembers(&monitoredItem->lastSampledValue);
monitoredItem->lastSampledValue = newValueAsByteString;
TAILQ_INSERT_TAIL(&monitoredItem->queue, newvalue, listEntry);
monitoredItem->currentQueueSize++;
}
UA_StatusCode MonitoredItem_registerSampleJob(UA_Server *server, UA_MonitoredItem *mon) {
//SampleCallback(server, mon);
UA_Job job = {.type = UA_JOBTYPE_METHODCALL,
.job.methodCall = {.method = (UA_ServerCallback)SampleCallback, .data = mon} };
UA_StatusCode retval = UA_Server_addRepeatedJob(server, job, (UA_UInt32)mon->samplingInterval,
&mon->sampleJobGuid);
if(retval == UA_STATUSCODE_GOOD)
mon->sampleJobIsRegistered = true;
return retval;
}
UA_StatusCode MonitoredItem_unregisterSampleJob(UA_Server *server, UA_MonitoredItem *mon) {
if(!mon->sampleJobIsRegistered)
return UA_STATUSCODE_GOOD;
mon->sampleJobIsRegistered = false;
return UA_Server_removeRepeatedJob(server, mon->sampleJobGuid);
}
/****************/
/* Subscription */
/****************/
UA_Subscription * UA_Subscription_new(UA_Session *session, UA_UInt32 subscriptionID) {
UA_Subscription *new = UA_malloc(sizeof(UA_Subscription));
if(!new)
return NULL;
new->session = session;
new->subscriptionID = subscriptionID;
new->sequenceNumber = 0;
new->maxKeepAliveCount = 0;
new->publishingEnabled = false;
memset(&new->publishJobGuid, 0, sizeof(UA_Guid));
new->publishJobIsRegistered = false;
new->currentKeepAliveCount = 0;
new->currentLifetimeCount = 0;
new->state = UA_SUBSCRIPTIONSTATE_LATE; /* The first publish response is sent immediately */
LIST_INIT(&new->retransmissionQueue);
LIST_INIT(&new->MonitoredItems);
return new;
}
void UA_Subscription_deleteMembers(UA_Subscription *subscription, UA_Server *server) {
Subscription_unregisterPublishJob(server, subscription);
/* Delete monitored Items */
UA_MonitoredItem *mon, *tmp_mon;
LIST_FOREACH_SAFE(mon, &subscription->MonitoredItems, listEntry, tmp_mon) {
LIST_REMOVE(mon, listEntry);
MonitoredItem_delete(server, mon);
}
/* Delete Retransmission Queue */
UA_NotificationMessageEntry *nme, *nme_tmp;
LIST_FOREACH_SAFE(nme, &subscription->retransmissionQueue, listEntry, nme_tmp) {
LIST_REMOVE(nme, listEntry);
UA_NotificationMessage_deleteMembers(&nme->message);
UA_free(nme);
}
}
UA_MonitoredItem *
UA_Subscription_getMonitoredItem(UA_Subscription *sub, UA_UInt32 monitoredItemID) {
UA_MonitoredItem *mon;
LIST_FOREACH(mon, &sub->MonitoredItems, listEntry) {
if(mon->itemId == monitoredItemID)
break;
}
return mon;
}
UA_StatusCode
UA_Subscription_deleteMonitoredItem(UA_Server *server, UA_Subscription *sub,
UA_UInt32 monitoredItemID) {
UA_MonitoredItem *mon;
LIST_FOREACH(mon, &sub->MonitoredItems, listEntry) {
if(mon->itemId == monitoredItemID) {
LIST_REMOVE(mon, listEntry);
MonitoredItem_delete(server, mon);
return UA_STATUSCODE_GOOD;
}
}
return UA_STATUSCODE_BADMONITOREDITEMIDINVALID;
}
void UA_Subscription_publishCallback(UA_Server *server, UA_Subscription *sub) {
/* Count the available notifications */
size_t notifications = 0;
UA_Boolean moreNotifications = false;
if(sub->publishingEnabled) {
UA_MonitoredItem *mon;
LIST_FOREACH(mon, &sub->MonitoredItems, listEntry) {
MonitoredItem_queuedValue *qv;
TAILQ_FOREACH(qv, &mon->queue, listEntry) {
if(notifications >= sub->notificationsPerPublish) {
moreNotifications = true;
break;
}
notifications++;
}
}
}
/* Return if nothing to do */
if(notifications == 0) {
sub->currentKeepAliveCount++;
if(sub->currentKeepAliveCount < sub->maxKeepAliveCount)
return;
}
/* Check if the securechannel is valid */
UA_SecureChannel *channel = sub->session->channel;
if(!channel)
return;
/* Dequeue a response */
UA_PublishResponseEntry *pre = SIMPLEQ_FIRST(&sub->session->responseQueue);
if(!pre) {
UA_LOG_DEBUG(server->config.logger, UA_LOGCATEGORY_SERVER,
"Cannot send a publish response on subscription %u " \
"since the publish queue is empty on session %u",
sub->subscriptionID, sub->session->authenticationToken.identifier.numeric);
if(sub->state != UA_SUBSCRIPTIONSTATE_LATE) {
sub->state = UA_SUBSCRIPTIONSTATE_LATE;
} else {
sub->currentLifetimeCount++;
if(sub->currentLifetimeCount >= sub->lifeTimeCount) {
UA_LOG_INFO(server->config.logger, UA_LOGCATEGORY_SERVER,
"End of lifetime for subscription %u on session %u",
sub->subscriptionID, sub->session->authenticationToken.identifier.numeric);
UA_Session_deleteSubscription(server, sub->session, sub->subscriptionID);
}
}
return;
}
SIMPLEQ_REMOVE_HEAD(&sub->session->responseQueue, listEntry);
UA_PublishResponse *response = &pre->response;
UA_UInt32 requestId = pre->requestId;
/* We have a request. Reset state to normal. */
sub->state = UA_SUBSCRIPTIONSTATE_NORMAL;
sub->currentKeepAliveCount = 0;
sub->currentLifetimeCount = 0;
/* Prepare the response */
response->responseHeader.timestamp = UA_DateTime_now();
response->subscriptionId = sub->subscriptionID;
response->moreNotifications = moreNotifications;
UA_NotificationMessage *message = &response->notificationMessage;
message->publishTime = response->responseHeader.timestamp;
if(notifications == 0) {
/* Send sequence number for the next notification */
message->sequenceNumber = sub->sequenceNumber + 1;
} else {
/* Increase the sequence number */
message->sequenceNumber = ++sub->sequenceNumber;
/* Collect the notification messages */
message->notificationData = UA_ExtensionObject_new();
message->notificationDataSize = 1;
UA_ExtensionObject *data = message->notificationData;
UA_DataChangeNotification *dcn = UA_DataChangeNotification_new();
dcn->monitoredItems = UA_Array_new(notifications, &UA_TYPES[UA_TYPES_MONITOREDITEMNOTIFICATION]);
dcn->monitoredItemsSize = notifications;
size_t l = 0;
UA_MonitoredItem *mon;
LIST_FOREACH(mon, &sub->MonitoredItems, listEntry) {
MonitoredItem_queuedValue *qv, *qv_tmp;
TAILQ_FOREACH_SAFE(qv, &mon->queue, listEntry, qv_tmp) {
if(notifications <= l)
break;
UA_MonitoredItemNotification *min = &dcn->monitoredItems[l];
min->clientHandle = qv->clientHandle;
min->value = qv->value;
TAILQ_REMOVE(&mon->queue, qv, listEntry);
UA_free(qv);
mon->currentQueueSize--;
l++;
}
}
data->encoding = UA_EXTENSIONOBJECT_DECODED;
data->content.decoded.data = dcn;
data->content.decoded.type = &UA_TYPES[UA_TYPES_DATACHANGENOTIFICATION];
/* Put the notification message into the retransmission queue */
UA_NotificationMessageEntry *retransmission = malloc(sizeof(UA_NotificationMessageEntry));
retransmission->message = response->notificationMessage;
LIST_INSERT_HEAD(&sub->retransmissionQueue, retransmission, listEntry);
}
/* Get the available sequence numbers from the retransmission queue */
size_t available = 0, i = 0;
UA_NotificationMessageEntry *nme;
LIST_FOREACH(nme, &sub->retransmissionQueue, listEntry)
available++;
//cppcheck-suppress knownConditionTrueFalse
if(available > 0) {
response->availableSequenceNumbers = UA_alloca(available * sizeof(UA_UInt32));
response->availableSequenceNumbersSize = available;
}
LIST_FOREACH(nme, &sub->retransmissionQueue, listEntry) {
response->availableSequenceNumbers[i] = nme->message.sequenceNumber;
i++;
}
/* Send the response */
UA_LOG_DEBUG(server->config.logger, UA_LOGCATEGORY_SERVER,
"Sending out a publish response on subscription %u on securechannel %u " \
"with %u notifications", sub->subscriptionID,
sub->session->authenticationToken.identifier.numeric, (UA_UInt32)notifications);
UA_SecureChannel_sendBinaryMessage(sub->session->channel, requestId, response,
&UA_TYPES[UA_TYPES_PUBLISHRESPONSE]);
/* Remove the queued request */
UA_NotificationMessage_init(&response->notificationMessage); /* message was copied to the queue */
response->availableSequenceNumbers = NULL; /* stack-allocated */
response->availableSequenceNumbersSize = 0;
UA_PublishResponse_deleteMembers(&pre->response);
UA_free(pre);
/* Repeat if there are more notifications to send */
if(moreNotifications)
UA_Subscription_publishCallback(server, sub);
}
UA_StatusCode Subscription_registerPublishJob(UA_Server *server, UA_Subscription *sub) {
UA_Job job = (UA_Job) {.type = UA_JOBTYPE_METHODCALL,
.job.methodCall = {.method = (UA_ServerCallback)UA_Subscription_publishCallback,
.data = sub} };
UA_LOG_DEBUG(server->config.logger, UA_LOGCATEGORY_SERVER,
"Adding a subscription with %i millisec interval", (int)sub->publishingInterval);
UA_StatusCode retval = UA_Server_addRepeatedJob(server, job,
(UA_UInt32)sub->publishingInterval,
&sub->publishJobGuid);
if(retval == UA_STATUSCODE_GOOD)
sub->publishJobIsRegistered = true;
else
UA_LOG_DEBUG(server->config.logger, UA_LOGCATEGORY_SERVER,
"Could not register a subscription publication job " \
"with status code 0x%08x\n", retval);
return retval;
}
UA_StatusCode Subscription_unregisterPublishJob(UA_Server *server, UA_Subscription *sub) {
if(!sub->publishJobIsRegistered)
return UA_STATUSCODE_GOOD;
sub->publishJobIsRegistered = false;
UA_StatusCode retval = UA_Server_removeRepeatedJob(server, sub->publishJobGuid);
if(retval != UA_STATUSCODE_GOOD)
UA_LOG_DEBUG(server->config.logger, UA_LOGCATEGORY_SERVER,
"Could not remove a subscription publication job " \
"with status code 0x%08x\n", retval);
return retval;
}
#endif /* UA_ENABLE_SUBSCRIPTIONS */
/*********************************** amalgamated original file "/home/wn/Sources/open62541-open62541-395ce48/src/server/ua_services_subscription.c" ***********************************/
#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 void
setSubscriptionSettings(UA_Server *server, UA_Subscription *subscription,
UA_Double requestedPublishingInterval,
UA_UInt32 requestedLifetimeCount,
UA_UInt32 requestedMaxKeepAliveCount,
UA_UInt32 maxNotificationsPerPublish, UA_Byte priority) {
Subscription_unregisterPublishJob(server, 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;
Subscription_registerPublishJob(server, subscription);
}
void Service_CreateSubscription(UA_Server *server, UA_Session *session,
const UA_CreateSubscriptionRequest *request,
UA_CreateSubscriptionResponse *response) {
response->subscriptionId = UA_Session_getUniqueSubscriptionID(session);
UA_Subscription *newSubscription = UA_Subscription_new(session, response->subscriptionId);
if(!newSubscription) {
response->responseHeader.serviceResult = UA_STATUSCODE_BADOUTOFMEMORY;
return;
}
UA_Session_addSubscription(session, newSubscription);
newSubscription->publishingEnabled = request->publishingEnabled;
setSubscriptionSettings(server, newSubscription, request->requestedPublishingInterval,
request->requestedLifetimeCount, request->requestedMaxKeepAliveCount,
request->maxNotificationsPerPublish, request->priority);
/* immediately send the first response */
newSubscription->currentKeepAliveCount = newSubscription->maxKeepAliveCount;
response->revisedPublishingInterval = newSubscription->publishingInterval;
response->revisedLifetimeCount = newSubscription->lifeTimeCount;
response->revisedMaxKeepAliveCount = newSubscription->maxKeepAliveCount;
}
void Service_ModifySubscription(UA_Server *server, UA_Session *session,
const UA_ModifySubscriptionRequest *request,
UA_ModifySubscriptionResponse *response) {
UA_Subscription *sub = UA_Session_getSubscriptionByID(session, request->subscriptionId);
if(!sub) {
response->responseHeader.serviceResult = UA_STATUSCODE_BADSUBSCRIPTIONIDINVALID;
return;
}
setSubscriptionSettings(server, sub, request->requestedPublishingInterval,
request->requestedLifetimeCount, request->requestedMaxKeepAliveCount,
request->maxNotificationsPerPublish, request->priority);
sub->currentLifetimeCount = 0; /* Reset the subscription lifetime */
response->revisedPublishingInterval = sub->publishingInterval;
response->revisedLifetimeCount = sub->lifeTimeCount;
response->revisedMaxKeepAliveCount = sub->maxKeepAliveCount;
return;
}
void Service_SetPublishingMode(UA_Server *server, UA_Session *session,
const UA_SetPublishingModeRequest *request,
UA_SetPublishingModeResponse *response) {
if(request->subscriptionIdsSize <= 0) {
response->responseHeader.serviceResult = UA_STATUSCODE_BADNOTHINGTODO;
return;
}
size_t size = request->subscriptionIdsSize;
response->results = UA_Array_new(size, &UA_TYPES[UA_TYPES_STATUSCODE]);
if(!response->results) {
response->responseHeader.serviceResult = UA_STATUSCODE_BADOUTOFMEMORY;
return;
}
response->resultsSize = size;
for(size_t i = 0; i < size; i++) {
UA_Subscription *sub = UA_Session_getSubscriptionByID(session, request->subscriptionIds[i]);
if(!sub) {
response->results[i] = UA_STATUSCODE_BADSUBSCRIPTIONIDINVALID;
continue;
}
sub->publishingEnabled = request->publishingEnabled;
sub->currentLifetimeCount = 0; /* Reset the subscription lifetime */
}
}
static void
setMonitoredItemSettings(UA_Server *server, UA_MonitoredItem *mon,
UA_MonitoringMode monitoringMode, UA_UInt32 clientHandle,
UA_Double samplingInterval, UA_UInt32 queueSize,
UA_Boolean discardOldest) {
MonitoredItem_unregisterSampleJob(server, mon);
mon->monitoringMode = monitoringMode;
mon->clientHandle = clientHandle;
mon->samplingInterval = samplingInterval;
UA_BOUNDEDVALUE_SETWBOUNDS(server->config.samplingIntervalLimits,
samplingInterval, mon->samplingInterval);
/* Check for nan */
if(samplingInterval != samplingInterval)
mon->samplingInterval = server->config.samplingIntervalLimits.min;
UA_BOUNDEDVALUE_SETWBOUNDS(server->config.queueSizeLimits,
queueSize, mon->maxQueueSize);
mon->discardOldest = discardOldest;
MonitoredItem_registerSampleJob(server, mon);
}
static const UA_String binaryEncoding = {sizeof("DefaultBinary")-1, (UA_Byte*)"DefaultBinary"};
static void
Service_CreateMonitoredItems_single(UA_Server *server, UA_Session *session, UA_Subscription *sub,
const UA_TimestampsToReturn timestampsToReturn,
const UA_MonitoredItemCreateRequest *request,
UA_MonitoredItemCreateResult *result) {
/* Check if the target exists */
const UA_Node *target = UA_NodeStore_get(server->nodestore, &request->itemToMonitor.nodeId);
if(!target) {
result->statusCode = UA_STATUSCODE_BADNODEIDINVALID;
return;
}
// TODO: Check if the target node type has the requested attribute
/* Check if the encoding is supported */
if(request->itemToMonitor.dataEncoding.name.length > 0 &&
!UA_String_equal(&binaryEncoding, &request->itemToMonitor.dataEncoding.name)) {
result->statusCode = UA_STATUSCODE_BADDATAENCODINGUNSUPPORTED;
return;
}
/* Create the monitoreditem */
UA_MonitoredItem *newMon = UA_MonitoredItem_new();
if(!newMon) {
result->statusCode = UA_STATUSCODE_BADOUTOFMEMORY;
return;
}
UA_StatusCode retval = UA_NodeId_copy(&target->nodeId, &newMon->monitoredNodeId);
if(retval != UA_STATUSCODE_GOOD) {
result->statusCode = retval;
MonitoredItem_delete(server, newMon);
return;
}
newMon->subscription = sub;
newMon->attributeID = request->itemToMonitor.attributeId;
newMon->itemId = UA_Session_getUniqueSubscriptionID(session);
newMon->timestampsToReturn = timestampsToReturn;
setMonitoredItemSettings(server, newMon, request->monitoringMode,
request->requestedParameters.clientHandle,
request->requestedParameters.samplingInterval,
request->requestedParameters.queueSize,
request->requestedParameters.discardOldest);
LIST_INSERT_HEAD(&sub->MonitoredItems, newMon, listEntry);
/* Prepare the response */
UA_String_copy(&request->itemToMonitor.indexRange, &newMon->indexRange);
result->revisedSamplingInterval = newMon->samplingInterval;
result->revisedQueueSize = newMon->maxQueueSize;
result->monitoredItemId = newMon->itemId;
}
void
Service_CreateMonitoredItems(UA_Server *server, UA_Session *session,
const UA_CreateMonitoredItemsRequest *request,
UA_CreateMonitoredItemsResponse *response) {
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;
if(request->itemsToCreateSize <= 0) {
response->responseHeader.serviceResult = UA_STATUSCODE_BADNOTHINGTODO;
return;
}
response->results = UA_Array_new(request->itemsToCreateSize,
&UA_TYPES[UA_TYPES_MONITOREDITEMCREATERESULT]);
if(!response->results) {
response->responseHeader.serviceResult = UA_STATUSCODE_BADOUTOFMEMORY;
return;
}
response->resultsSize = request->itemsToCreateSize;
for(size_t i = 0; i < request->itemsToCreateSize; i++)
Service_CreateMonitoredItems_single(server, session, sub, request->timestampsToReturn,
&request->itemsToCreate[i], &response->results[i]);
}
static void
Service_ModifyMonitoredItems_single(UA_Server *server, UA_Session *session, UA_Subscription *sub,
const UA_MonitoredItemModifyRequest *request,
UA_MonitoredItemModifyResult *result) {
UA_MonitoredItem *mon = UA_Subscription_getMonitoredItem(sub, request->monitoredItemId);
if(!mon) {
result->statusCode = UA_STATUSCODE_BADMONITOREDITEMIDINVALID;
return;
}
setMonitoredItemSettings(server, mon, mon->monitoringMode,
request->requestedParameters.clientHandle,
request->requestedParameters.samplingInterval,
request->requestedParameters.queueSize,
request->requestedParameters.discardOldest);
result->revisedSamplingInterval = mon->samplingInterval;
result->revisedQueueSize = mon->maxQueueSize;
}
void Service_ModifyMonitoredItems(UA_Server *server, UA_Session *session,
const UA_ModifyMonitoredItemsRequest *request,
UA_ModifyMonitoredItemsResponse *response) {
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;
if(request->itemsToModifySize <= 0) {
response->responseHeader.serviceResult = UA_STATUSCODE_BADNOTHINGTODO;
return;
}
response->results = UA_Array_new(request->itemsToModifySize,
&UA_TYPES[UA_TYPES_MONITOREDITEMMODIFYRESULT]);
if(!response->results) {
response->responseHeader.serviceResult = UA_STATUSCODE_BADOUTOFMEMORY;
return;
}
response->resultsSize = request->itemsToModifySize;
for(size_t i = 0; i < request->itemsToModifySize; i++)
Service_ModifyMonitoredItems_single(server, session, sub, &request->itemsToModify[i],
&response->results[i]);
}
void
Service_Publish(UA_Server *server, UA_Session *session,
const UA_PublishRequest *request, UA_UInt32 requestId) {
/* Return an error if the session has no subscription */
if(LIST_EMPTY(&session->serverSubscriptions)) {
UA_PublishResponse response;
UA_PublishResponse_init(&response);
response.responseHeader.requestHandle = request->requestHeader.requestHandle;
response.responseHeader.serviceResult = UA_STATUSCODE_BADNOSUBSCRIPTION;
UA_SecureChannel_sendBinaryMessage(session->channel, requestId, &response,
&UA_TYPES[UA_TYPES_PUBLISHRESPONSE]);
return;
}
// todo error handling for malloc
UA_PublishResponseEntry *entry = UA_malloc(sizeof(UA_PublishResponseEntry));
entry->requestId = requestId;
UA_PublishResponse *response = &entry->response;
UA_PublishResponse_init(response);
response->responseHeader.requestHandle = request->requestHeader.requestHandle;
/* Delete Acknowledged Subscription Messages */
response->results = UA_malloc(request->subscriptionAcknowledgementsSize * sizeof(UA_StatusCode));
if(!response->results) {
response->responseHeader.serviceResult = UA_STATUSCODE_BADOUTOFMEMORY;
return;
}
response->resultsSize = request->subscriptionAcknowledgementsSize;
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(server->config.logger, UA_LOGCATEGORY_SERVER,
"Cannot process acknowledgements subscription %u", ack->subscriptionId);
continue;
}
response->results[i] = UA_STATUSCODE_BADSEQUENCENUMBERUNKNOWN;
UA_NotificationMessageEntry *pre, *pre_tmp;
LIST_FOREACH_SAFE(pre, &sub->retransmissionQueue, listEntry, pre_tmp) {
if(pre->message.sequenceNumber == ack->sequenceNumber) {
LIST_REMOVE(pre, listEntry);
response->results[i] = UA_STATUSCODE_GOOD;
UA_NotificationMessage_deleteMembers(&pre->message);
UA_free(pre);
break;
}
}
}
/* Queue the publish response */
SIMPLEQ_INSERT_TAIL(&session->responseQueue, entry, listEntry);
UA_LOG_DEBUG(server->config.logger, UA_LOGCATEGORY_SERVER,
"Queued a publication message on session %u",
session->authenticationToken.identifier.numeric);
/* Answer immediately to a late subscription */
UA_Subscription *immediate;
LIST_FOREACH(immediate, &session->serverSubscriptions, listEntry) {
if(immediate->state == UA_SUBSCRIPTIONSTATE_LATE) {
UA_LOG_DEBUG(server->config.logger, UA_LOGCATEGORY_SERVER,
"Response on a late subscription on session %u",
session->authenticationToken.identifier.numeric);
UA_Subscription_publishCallback(server, immediate);
return;
}
}
}
void Service_DeleteSubscriptions(UA_Server *server, UA_Session *session,
const UA_DeleteSubscriptionsRequest *request,
UA_DeleteSubscriptionsResponse *response) {
response->results = UA_malloc(sizeof(UA_StatusCode) * request->subscriptionIdsSize);
if(!response->results) {
response->responseHeader.serviceResult = UA_STATUSCODE_BADOUTOFMEMORY;
return;
}
response->resultsSize = request->subscriptionIdsSize;
for(size_t i = 0; i < request->subscriptionIdsSize; i++)
response->results[i] = UA_Session_deleteSubscription(server, session, request->subscriptionIds[i]);
}
void Service_DeleteMonitoredItems(UA_Server *server, UA_Session *session,
const UA_DeleteMonitoredItemsRequest *request,
UA_DeleteMonitoredItemsResponse *response) {
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->results = UA_malloc(sizeof(UA_StatusCode) * request->monitoredItemIdsSize);
if(!response->results) {
response->responseHeader.serviceResult = UA_STATUSCODE_BADOUTOFMEMORY;
return;
}
response->resultsSize = request->monitoredItemIdsSize;
for(size_t i = 0; i < request->monitoredItemIdsSize; i++)
response->results[i] = UA_Subscription_deleteMonitoredItem(server, sub, request->monitoredItemIds[i]);
}
void Service_Republish(UA_Server *server, UA_Session *session, const UA_RepublishRequest *request,
UA_RepublishResponse *response) {
/* 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;
LIST_FOREACH(entry, &sub->retransmissionQueue, listEntry) {
if(entry->message.sequenceNumber == request->retransmitSequenceNumber)
break;
}
if(entry)
response->responseHeader.serviceResult =
UA_NotificationMessage_copy(&entry->message, &response->notificationMessage);
else
response->responseHeader.serviceResult = UA_STATUSCODE_BADMESSAGENOTAVAILABLE;
}
#endif /* UA_ENABLE_SUBSCRIPTIONS */
/*********************************** amalgamated original file "/home/wn/Sources/open62541-open62541-395ce48/src/client/ua_client_highlevel_subscriptions.c" ***********************************/
#ifdef UA_ENABLE_SUBSCRIPTIONS /* conditional compilation */
const UA_SubscriptionSettings UA_SubscriptionSettings_standard = {
.requestedPublishingInterval = 500.0,
.requestedLifetimeCount = 10000,
.requestedMaxKeepAliveCount = 1,
.maxNotificationsPerPublish = 10,
.publishingEnabled = true,
.priority = 0
};
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_Service_createSubscription(client, request);
UA_StatusCode retval = response.responseHeader.serviceResult;
if(retval == UA_STATUSCODE_GOOD) {
UA_Client_Subscription *newSub = UA_malloc(sizeof(UA_Client_Subscription));
LIST_INIT(&newSub->MonitoredItems);
newSub->LifeTime = response.revisedLifetimeCount;
newSub->KeepAliveCount = response.revisedMaxKeepAliveCount;
newSub->PublishingInterval = response.revisedPublishingInterval;
newSub->SubscriptionID = response.subscriptionId;
newSub->NotificationsPerPublish = request.maxNotificationsPerPublish;
newSub->Priority = request.priority;
if(newSubscriptionId)
*newSubscriptionId = newSub->SubscriptionID;
LIST_INSERT_HEAD(&client->subscriptions, newSub, listEntry);
}
UA_CreateSubscriptionResponse_deleteMembers(&response);
return retval;
}
UA_StatusCode UA_Client_Subscriptions_remove(UA_Client *client, UA_UInt32 subscriptionId) {
UA_Client_Subscription *sub;
UA_StatusCode retval = UA_STATUSCODE_GOOD;
LIST_FOREACH(sub, &client->subscriptions, listEntry) {
if(sub->SubscriptionID == subscriptionId)
break;
}
// Problem? We do not have this subscription registeres. Maybe the server should
// be consulted at this point?
if(!sub)
return UA_STATUSCODE_BADSUBSCRIPTIONIDINVALID;
UA_DeleteSubscriptionsRequest request;
UA_DeleteSubscriptionsRequest_init(&request);
request.subscriptionIdsSize = 1;
request.subscriptionIds = (UA_UInt32 *) UA_malloc(sizeof(UA_UInt32));
*request.subscriptionIds = sub->SubscriptionID;
UA_Client_MonitoredItem *mon, *tmpmon;
LIST_FOREACH_SAFE(mon, &sub->MonitoredItems, listEntry, tmpmon) {
retval |= UA_Client_Subscriptions_removeMonitoredItem(client, sub->SubscriptionID,
mon->MonitoredItemId);
}
if(retval != UA_STATUSCODE_GOOD) {
UA_DeleteSubscriptionsRequest_deleteMembers(&request);
return retval;
}
UA_DeleteSubscriptionsResponse response = UA_Client_Service_deleteSubscriptions(client, request);
if(response.resultsSize > 0)
retval = response.results[0];
else
retval = response.responseHeader.serviceResult;
if(retval == UA_STATUSCODE_GOOD) {
LIST_REMOVE(sub, listEntry);
UA_free(sub);
}
UA_DeleteSubscriptionsRequest_deleteMembers(&request);
UA_DeleteSubscriptionsResponse_deleteMembers(&response);
return retval;
}
UA_StatusCode
UA_Client_Subscriptions_addMonitoredItem(UA_Client *client, UA_UInt32 subscriptionId,
UA_NodeId nodeId, UA_UInt32 attributeID,
UA_MonitoredItemHandlingFunction handlingFunction,
void *handlingContext, UA_UInt32 *newMonitoredItemId) {
UA_Client_Subscription *sub;
LIST_FOREACH(sub, &client->subscriptions, listEntry) {
if(sub->SubscriptionID == subscriptionId)
break;
}
if(!sub)
return UA_STATUSCODE_BADSUBSCRIPTIONIDINVALID;
/* Send the request */
UA_CreateMonitoredItemsRequest request;
UA_CreateMonitoredItemsRequest_init(&request);
request.subscriptionId = subscriptionId;
UA_MonitoredItemCreateRequest item;
UA_MonitoredItemCreateRequest_init(&item);
item.itemToMonitor.nodeId = nodeId;
item.itemToMonitor.attributeId = attributeID;
item.monitoringMode = UA_MONITORINGMODE_REPORTING;
item.requestedParameters.clientHandle = ++(client->monitoredItemHandles);
item.requestedParameters.samplingInterval = sub->PublishingInterval;
item.requestedParameters.discardOldest = true;
item.requestedParameters.queueSize = 1;
request.itemsToCreate = &item;
request.itemsToCreateSize = 1;
UA_CreateMonitoredItemsResponse response = UA_Client_Service_createMonitoredItems(client, request);
// slight misuse of retval here to check if the deletion was successfull.
UA_StatusCode retval;
if(response.resultsSize == 0)
retval = response.responseHeader.serviceResult;
else
retval = response.results[0].statusCode;
if(retval != UA_STATUSCODE_GOOD) {
UA_CreateMonitoredItemsResponse_deleteMembers(&response);
return retval;
}
/* Create the handler */
UA_Client_MonitoredItem *newMon = UA_malloc(sizeof(UA_Client_MonitoredItem));
newMon->MonitoringMode = UA_MONITORINGMODE_REPORTING;
UA_NodeId_copy(&nodeId, &newMon->monitoredNodeId);
newMon->AttributeID = attributeID;
newMon->ClientHandle = client->monitoredItemHandles;
newMon->SamplingInterval = sub->PublishingInterval;
newMon->QueueSize = 1;
newMon->DiscardOldest = true;
newMon->handler = handlingFunction;
newMon->handlerContext = handlingContext;
newMon->MonitoredItemId = response.results[0].monitoredItemId;
LIST_INSERT_HEAD(&sub->MonitoredItems, newMon, listEntry);
*newMonitoredItemId = newMon->MonitoredItemId;
UA_LOG_DEBUG(client->config.logger, UA_LOGCATEGORY_CLIENT,
"Created a monitored item with client handle %u", client->monitoredItemHandles);
UA_CreateMonitoredItemsResponse_deleteMembers(&response);
return UA_STATUSCODE_GOOD;
}
UA_StatusCode
UA_Client_Subscriptions_removeMonitoredItem(UA_Client *client, UA_UInt32 subscriptionId,
UA_UInt32 monitoredItemId) {
UA_Client_Subscription *sub;
LIST_FOREACH(sub, &client->subscriptions, listEntry) {
if(sub->SubscriptionID == subscriptionId)
break;
}
if(!sub)
return UA_STATUSCODE_BADSUBSCRIPTIONIDINVALID;
UA_Client_MonitoredItem *mon;
LIST_FOREACH(mon, &sub->MonitoredItems, listEntry) {
if(mon->MonitoredItemId == monitoredItemId)
break;
}
if(!mon)
return UA_STATUSCODE_BADMONITOREDITEMIDINVALID;
UA_DeleteMonitoredItemsRequest request;
UA_DeleteMonitoredItemsRequest_init(&request);
request.subscriptionId = sub->SubscriptionID;
request.monitoredItemIdsSize = 1;
request.monitoredItemIds = (UA_UInt32 *) UA_malloc(sizeof(UA_UInt32));
request.monitoredItemIds[0] = mon->MonitoredItemId;
UA_DeleteMonitoredItemsResponse response = UA_Client_Service_deleteMonitoredItems(client, request);
UA_StatusCode retval = UA_STATUSCODE_GOOD;
if(response.resultsSize > 1)
retval = response.results[0];
else
retval = response.responseHeader.serviceResult;
if(retval == UA_STATUSCODE_GOOD) {
LIST_REMOVE(mon, listEntry);
UA_NodeId_deleteMembers(&mon->monitoredNodeId);
UA_free(mon);
}
UA_DeleteMonitoredItemsRequest_deleteMembers(&request);
UA_DeleteMonitoredItemsResponse_deleteMembers(&response);
return retval;
}
static void
UA_Client_processPublishResponse(UA_Client *client, UA_PublishResponse *response) {
if(response->responseHeader.serviceResult != UA_STATUSCODE_GOOD)
return;
/* Find the subscription */
UA_Client_Subscription *sub;
LIST_FOREACH(sub, &client->subscriptions, listEntry) {
if(sub->SubscriptionID == response->subscriptionId)
break;
}
if(!sub)
return;
UA_LOG_DEBUG(client->config.logger, UA_LOGCATEGORY_CLIENT,
"Processing a publish response on subscription %u with %u notifications",
sub->SubscriptionID, response->notificationMessage.notificationDataSize);
/* Check if the server has acknowledged any of our ACKS */
// TODO: The acks should be attached to the subscription
UA_Client_NotificationsAckNumber *ack, *tmpAck;
size_t i = 0;
LIST_FOREACH_SAFE(ack, &client->pendingNotificationsAcks, listEntry, tmpAck) {
if(response->results[i] == UA_STATUSCODE_GOOD ||
response->results[i] == UA_STATUSCODE_BADSEQUENCENUMBERUNKNOWN) {
LIST_REMOVE(ack, listEntry);
UA_free(ack);
}
i++;
}
/* Process the notification messages */
UA_NotificationMessage *msg = &response->notificationMessage;
for(size_t k = 0; k < msg->notificationDataSize; k++) {
if(msg->notificationData[k].encoding != UA_EXTENSIONOBJECT_DECODED)
continue;
/* Currently only dataChangeNotifications are supported */
if(msg->notificationData[k].content.decoded.type != &UA_TYPES[UA_TYPES_DATACHANGENOTIFICATION])
continue;
UA_DataChangeNotification *dataChangeNotification = msg->notificationData[k].content.decoded.data;
for(size_t j = 0; j < dataChangeNotification->monitoredItemsSize; j++) {
UA_MonitoredItemNotification *mitemNot = &dataChangeNotification->monitoredItems[j];
UA_Client_MonitoredItem *mon;
LIST_FOREACH(mon, &sub->MonitoredItems, listEntry) {
if(mon->ClientHandle == mitemNot->clientHandle) {
mon->handler(mon->MonitoredItemId, &mitemNot->value, mon->handlerContext);
break;
}
}
if(!mon)
UA_LOG_DEBUG(client->config.logger, UA_LOGCATEGORY_CLIENT,
"Could not process a notification with clienthandle %u on subscription %u",
mitemNot->clientHandle, sub->SubscriptionID);
}
}
/* Add to the list of pending acks */
tmpAck = UA_malloc(sizeof(UA_Client_NotificationsAckNumber));
tmpAck->subAck.sequenceNumber = msg->sequenceNumber;
tmpAck->subAck.subscriptionId = sub->SubscriptionID;
LIST_INSERT_HEAD(&client->pendingNotificationsAcks, tmpAck, listEntry);
}
UA_StatusCode UA_Client_Subscriptions_manuallySendPublishRequest(UA_Client *client) {
if (client->state == UA_CLIENTSTATE_ERRORED)
return UA_STATUSCODE_BADSERVERNOTCONNECTED;
UA_Boolean moreNotifications = true;
while(moreNotifications == true) {
UA_PublishRequest request;
UA_PublishRequest_init(&request);
request.subscriptionAcknowledgementsSize = 0;
UA_Client_NotificationsAckNumber *ack;
LIST_FOREACH(ack, &client->pendingNotificationsAcks, listEntry)
request.subscriptionAcknowledgementsSize++;
if(request.subscriptionAcknowledgementsSize > 0) {
request.subscriptionAcknowledgements =
UA_malloc(sizeof(UA_SubscriptionAcknowledgement) * request.subscriptionAcknowledgementsSize);
if(!request.subscriptionAcknowledgements)
return UA_STATUSCODE_GOOD;
}
int index = 0 ;
LIST_FOREACH(ack, &client->pendingNotificationsAcks, listEntry) {
request.subscriptionAcknowledgements[index].sequenceNumber = ack->subAck.sequenceNumber;
request.subscriptionAcknowledgements[index].subscriptionId = ack->subAck.subscriptionId;
index++;
}
UA_PublishResponse response = UA_Client_Service_publish(client, request);
UA_Client_processPublishResponse(client, &response);
moreNotifications = response.moreNotifications;
UA_PublishResponse_deleteMembers(&response);
UA_PublishRequest_deleteMembers(&request);
}
return UA_STATUSCODE_GOOD;
}
#endif /* UA_ENABLE_SUBSCRIPTIONS */
/*********************************** amalgamated original file "/home/wn/Sources/open62541-open62541-395ce48/plugins/networklayer_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.
*/
#include <stdlib.h> // malloc, free
#include <stdio.h> // snprintf
#include <string.h> // memset
#include <errno.h>
#ifdef _WIN32
# include <malloc.h>
# include <winsock2.h>
# include <ws2tcpip.h>
# define CLOSESOCKET(S) closesocket(S)
# define ssize_t long
#else
# include <fcntl.h>
# include <sys/select.h>
# include <netinet/in.h>
# ifndef __CYGWIN__
# include <netinet/tcp.h>
# endif
# include <sys/ioctl.h>
# include <netdb.h> //gethostbyname for the client
# include <unistd.h> // read, write, close
# include <arpa/inet.h>
# ifdef __QNX__
# include <sys/socket.h>
# endif
# define CLOSESOCKET(S) close(S)
#endif
/* workaround a glibc bug where an integer conversion is required */
#if !defined(_WIN32)
# if defined(__GNU_LIBRARY__) && (__GNU_LIBRARY__ >= 6) && (__GLIBC__ >= 2) && (__GLIBC_MINOR__ >= 16)
# define UA_fd_set(fd, fds) FD_SET(fd, fds)
# define UA_fd_isset(fd, fds) FD_ISSET(fd, fds)
# else
# define UA_fd_set(fd, fds) FD_SET((unsigned int)fd, fds)
# define UA_fd_isset(fd, fds) FD_ISSET((unsigned int)fd, fds)
# endif
#else
# define UA_fd_set(fd, fds) FD_SET((unsigned int)fd, fds)
# define UA_fd_isset(fd, fds) FD_ISSET((unsigned int)fd, fds)
#endif
#ifdef UA_ENABLE_MULTITHREADING
# include <urcu/uatomic.h>
#endif
#ifndef MSG_NOSIGNAL
#define MSG_NOSIGNAL 0
#endif
/****************************/
/* Generic Socket Functions */
/****************************/
static void
socket_close(UA_Connection *connection) {
connection->state = UA_CONNECTION_CLOSED;
shutdown(connection->sockfd,2);
CLOSESOCKET(connection->sockfd);
}
static UA_StatusCode
socket_write(UA_Connection *connection, UA_ByteString *buf) {
size_t nWritten = 0;
do {
ssize_t n = 0;
do {
#ifdef _WIN32
n = send((SOCKET)connection->sockfd, (const char*)buf->data, buf->length, 0);
const int last_error = WSAGetLastError();
if(n < 0 && last_error != WSAEINTR && last_error != WSAEWOULDBLOCK) {
connection->close(connection);
socket_close(connection);
UA_ByteString_deleteMembers(buf);
return UA_STATUSCODE_BADCONNECTIONCLOSED;
}
#else
n = send(connection->sockfd, (const char*)buf->data, buf->length, MSG_NOSIGNAL);
if(n == -1L && errno != EINTR && errno != EAGAIN) {
connection->close(connection);
socket_close(connection);
UA_ByteString_deleteMembers(buf);
return UA_STATUSCODE_BADCONNECTIONCLOSED;
}
#endif
} while(n == -1L);
nWritten += (size_t)n;
} while(nWritten < buf->length);
UA_ByteString_deleteMembers(buf);
return UA_STATUSCODE_GOOD;
}
static UA_StatusCode
socket_recv(UA_Connection *connection, UA_ByteString *response, UA_UInt32 timeout) {
response->data = malloc(connection->localConf.recvBufferSize);
if(!response->data) {
response->length = 0;
return UA_STATUSCODE_BADOUTOFMEMORY; /* not enough memory retry */
}
if(timeout > 0) {
/* currently, only the client uses timeouts */
#ifndef _WIN32
UA_UInt32 timeout_usec = timeout * 1000;
#ifdef __APPLE__
struct timeval tmptv = {(long int)(timeout_usec / 1000000), timeout_usec % 1000000};
#else
struct timeval tmptv = {(long int)(timeout_usec / 1000000), (long int)(timeout_usec % 1000000)};
#endif
int ret = setsockopt(connection->sockfd, SOL_SOCKET, SO_RCVTIMEO, (const char *)&tmptv, sizeof(struct timeval));
#else
DWORD timeout_dw = timeout;
int ret = setsockopt(connection->sockfd, SOL_SOCKET, SO_RCVTIMEO, (const char*)&timeout_dw, sizeof(DWORD));
#endif
if(0 != ret) {
UA_ByteString_deleteMembers(response);
socket_close(connection);
return UA_STATUSCODE_BADCONNECTIONCLOSED;
}
}
#ifdef __CYGWIN__
/* WORKAROUND for https://cygwin.com/ml/cygwin/2013-07/msg00107.html */
ssize_t ret;
if (timeout > 0) {
fd_set fdset;
UA_UInt32 timeout_usec = timeout * 1000;
#ifdef __APPLE__
struct timeval tmptv = {(long int)(timeout_usec / 1000000), timeout_usec % 1000000};
#else
struct timeval tmptv = {(long int)(timeout_usec / 1000000), (long int)(timeout_usec % 1000000)};
#endif
UA_Int32 retval;
FD_ZERO(&fdset);
UA_fd_set(connection->sockfd, &fdset);
retval = select(connection->sockfd+1, &fdset, NULL, NULL, &tmptv);
if(retval && UA_fd_isset(connection->sockfd, &fdset)) {
ret = recv(connection->sockfd, (char*)response->data, connection->localConf.recvBufferSize, 0);
} else {
ret = 0;
}
} else {
ret = recv(connection->sockfd, (char*)response->data, connection->localConf.recvBufferSize, 0);
}
#else
ssize_t ret = recv(connection->sockfd, (char*)response->data, connection->localConf.recvBufferSize, 0);
#endif
if(ret == 0) {
/* server has closed the connection */
UA_ByteString_deleteMembers(response);
socket_close(connection);
return UA_STATUSCODE_BADCONNECTIONCLOSED;
} else if(ret < 0) {
UA_ByteString_deleteMembers(response);
#ifdef _WIN32
const int last_error = WSAGetLastError();
#define TEST_RETRY (last_error == WSAEINTR || (timeout > 0) ? 0 : (last_error == WSAEWOULDBLOCK))
#else
#define TEST_RETRY (errno == EINTR || (timeout > 0) ? 0 : (errno == EAGAIN || errno == EWOULDBLOCK))
#endif
if (TEST_RETRY)
return UA_STATUSCODE_GOOD; /* retry */
else {
socket_close(connection);
return UA_STATUSCODE_BADCONNECTIONCLOSED;
}
}
response->length = (size_t)ret;
return UA_STATUSCODE_GOOD;
}
static UA_StatusCode socket_set_nonblocking(UA_Int32 sockfd) {
#ifdef _WIN32
u_long iMode = 1;
if(ioctlsocket(sockfd, FIONBIO, &iMode) != NO_ERROR)
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 void FreeConnectionCallback(UA_Server *server, void *ptr) {
UA_Connection_deleteMembers((UA_Connection*)ptr);
free(ptr);
}
/***************************/
/* Server NetworkLayer TCP */
/***************************/
/**
* For the multithreaded mode, assume a single thread that periodically "gets work" from the network
* layer. In addition, several worker threads are asynchronously calling into the callbacks of the
* UA_Connection that holds a single connection.
*
* Creating a connection: When "GetWork" encounters a new connection, it creates a UA_Connection
* with the socket information. This is added to the mappings array that links sockets to
* UA_Connection structs.
*
* Reading data: In "GetWork", we listen on the sockets in the mappings array. If data arrives (or
* the connection closes), a WorkItem is created that carries the work and a pointer to the
* connection.
*
* Closing a connection: Closing can happen in two ways. Either it is triggered by the server in an
* asynchronous callback. Or the connection is close by the client and this is detected in
* "GetWork". The server needs to do some internal cleanups (close attached securechannels, etc.).
* So even when a closed connection is detected in "GetWork", we trigger the server to close the
* connection (with a WorkItem) and continue from the callback.
*
* - Server calls close-callback: We close the socket, set the connection-state to closed and add
* the connection to a linked list from which it is deleted later. The connection cannot be freed
* right away since other threads might still be using it.
*
* - GetWork: We remove the connection from the mappings array. In the non-multithreaded case, the
* connection is freed. For multithreading, we return a workitem that is delayed, i.e. that is
* called only after all workitems created before are finished in all threads. This workitems
* contains a callback that goes through the linked list of connections to be freed.
*
*/
#define MAXBACKLOG 100
typedef struct {
UA_ConnectionConfig conf;
UA_UInt16 port;
UA_Logger logger; // Set during start
/* open sockets and connections */
UA_Int32 serversockfd;
size_t mappingsSize;
struct ConnectionMapping {
UA_Connection *connection;
UA_Int32 sockfd;
} *mappings;
} ServerNetworkLayerTCP;
static UA_StatusCode
ServerNetworkLayerGetSendBuffer(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
ServerNetworkLayerReleaseSendBuffer(UA_Connection *connection, UA_ByteString *buf) {
UA_ByteString_deleteMembers(buf);
}
static void
ServerNetworkLayerReleaseRecvBuffer(UA_Connection *connection, UA_ByteString *buf) {
UA_ByteString_deleteMembers(buf);
}
/* after every select, we need to reset the sockets we want to listen on */
static UA_Int32
setFDSet(ServerNetworkLayerTCP *layer, fd_set *fdset) {
FD_ZERO(fdset);
UA_fd_set(layer->serversockfd, fdset);
UA_Int32 highestfd = layer->serversockfd;
for(size_t i = 0; i < layer->mappingsSize; i++) {
UA_fd_set(layer->mappings[i].sockfd, fdset);
if(layer->mappings[i].sockfd > highestfd)
highestfd = layer->mappings[i].sockfd;
}
return highestfd;
}
/* callback triggered from the server */
static void
ServerNetworkLayerTCP_closeConnection(UA_Connection *connection) {
#ifdef UA_ENABLE_MULTITHREADING
if(uatomic_xchg(&connection->state, UA_CONNECTION_CLOSED) == UA_CONNECTION_CLOSED)
return;
#else
if(connection->state == UA_CONNECTION_CLOSED)
return;
connection->state = UA_CONNECTION_CLOSED;
#endif
//cppcheck-suppress unreadVariable
ServerNetworkLayerTCP *layer = connection->handle;
UA_LOG_INFO(layer->logger, UA_LOGCATEGORY_NETWORK, "Closing the Connection %i",
connection->sockfd);
/* only "shutdown" here. this triggers the select, where the socket is
"closed" in the mainloop */
shutdown(connection->sockfd, 2);
}
/* call only from the single networking thread */
static UA_StatusCode
ServerNetworkLayerTCP_add(ServerNetworkLayerTCP *layer, UA_Int32 newsockfd) {
UA_Connection *c = malloc(sizeof(UA_Connection));
if(!c)
return UA_STATUSCODE_BADINTERNALERROR;
struct sockaddr_in addr;
socklen_t addrlen = sizeof(struct sockaddr_in);
getpeername(newsockfd, (struct sockaddr*)&addr, &addrlen);
UA_LOG_INFO(layer->logger, UA_LOGCATEGORY_NETWORK, "New Connection %i over TCP from %s:%d",
newsockfd, inet_ntoa(addr.sin_addr), ntohs(addr.sin_port));
UA_Connection_init(c);
c->sockfd = newsockfd;
c->handle = layer;
c->localConf = layer->conf;
c->send = socket_write;
c->close = ServerNetworkLayerTCP_closeConnection;
c->getSendBuffer = ServerNetworkLayerGetSendBuffer;
c->releaseSendBuffer = ServerNetworkLayerReleaseSendBuffer;
c->releaseRecvBuffer = ServerNetworkLayerReleaseRecvBuffer;
c->state = UA_CONNECTION_OPENING;
struct ConnectionMapping *nm;
nm = realloc(layer->mappings, sizeof(struct ConnectionMapping)*(layer->mappingsSize+1));
if(!nm) {
UA_LOG_ERROR(layer->logger, UA_LOGCATEGORY_NETWORK, "No memory for a new Connection");
free(c);
return UA_STATUSCODE_BADINTERNALERROR;
}
layer->mappings = nm;
layer->mappings[layer->mappingsSize] = (struct ConnectionMapping){c, newsockfd};
layer->mappingsSize++;
return UA_STATUSCODE_GOOD;
}
static UA_StatusCode
ServerNetworkLayerTCP_start(UA_ServerNetworkLayer *nl, UA_Logger logger) {
ServerNetworkLayerTCP *layer = nl->handle;
layer->logger = logger;
/* get the discovery url from the hostname */
UA_String du = UA_STRING_NULL;
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);
/* open the server socket */
#ifdef _WIN32
if((layer->serversockfd = socket(PF_INET, SOCK_STREAM,0)) == (UA_Int32)INVALID_SOCKET) {
UA_LOG_WARNING(layer->logger, UA_LOGCATEGORY_NETWORK, "Error opening socket, code: %d",
WSAGetLastError());
return UA_STATUSCODE_BADINTERNALERROR;
}
#else
if((layer->serversockfd = socket(PF_INET, SOCK_STREAM, 0)) < 0) {
UA_LOG_WARNING(layer->logger, UA_LOGCATEGORY_NETWORK, "Error opening socket");
return UA_STATUSCODE_BADINTERNALERROR;
}
#endif
const struct sockaddr_in serv_addr =
{.sin_family = AF_INET, .sin_addr.s_addr = INADDR_ANY,
.sin_port = htons(layer->port), .sin_zero = {0}};
int optval = 1;
if(setsockopt(layer->serversockfd, SOL_SOCKET,
SO_REUSEADDR, (const char *)&optval, sizeof(optval)) == -1) {
UA_LOG_WARNING(layer->logger, UA_LOGCATEGORY_NETWORK,
"Error during setting of socket options");
CLOSESOCKET(layer->serversockfd);
return UA_STATUSCODE_BADINTERNALERROR;
}
if(bind(layer->serversockfd, (const struct sockaddr *)&serv_addr,
sizeof(serv_addr)) < 0) {
UA_LOG_WARNING(layer->logger, UA_LOGCATEGORY_NETWORK, "Error during socket binding");
CLOSESOCKET(layer->serversockfd);
return UA_STATUSCODE_BADINTERNALERROR;
}
socket_set_nonblocking(layer->serversockfd);
listen(layer->serversockfd, MAXBACKLOG);
UA_LOG_INFO(layer->logger, UA_LOGCATEGORY_NETWORK, "TCP network layer listening on %.*s",
nl->discoveryUrl.length, nl->discoveryUrl.data);
return UA_STATUSCODE_GOOD;
}
static size_t
ServerNetworkLayerTCP_getJobs(UA_ServerNetworkLayer *nl, UA_Job **jobs, UA_UInt16 timeout) {
ServerNetworkLayerTCP *layer = nl->handle;
fd_set fdset, errset;
UA_Int32 highestfd = setFDSet(layer, &fdset);
setFDSet(layer, &errset);
struct timeval tmptv = {0, timeout * 1000};
UA_Int32 resultsize;
resultsize = select(highestfd+1, &fdset, NULL, &errset, &tmptv);
if(resultsize < 0) {
*jobs = NULL;
return 0;
}
/* accept new connections (can only be a single one) */
if(UA_fd_isset(layer->serversockfd, &fdset)) {
resultsize--;
struct sockaddr_in cli_addr;
socklen_t cli_len = sizeof(cli_addr);
int newsockfd = accept(layer->serversockfd, (struct sockaddr *) &cli_addr, &cli_len);
int i = 1;
setsockopt(newsockfd, IPPROTO_TCP, TCP_NODELAY, (void *)&i, sizeof(i));
if(newsockfd >= 0) {
socket_set_nonblocking(newsockfd);
ServerNetworkLayerTCP_add(layer, newsockfd);
}
}
/* alloc enough space for a cleanup-connection and free-connection job per resulted socket */
if(resultsize == 0)
return 0;
UA_Job *js = malloc(sizeof(UA_Job) * (size_t)resultsize * 2);
if(!js)
return 0;
/* read from established sockets */
size_t j = 0;
UA_ByteString buf = UA_BYTESTRING_NULL;
for(size_t i = 0; i < layer->mappingsSize && j < (size_t)resultsize; i++) {
if(!UA_fd_isset(layer->mappings[i].sockfd, &errset) && !UA_fd_isset(layer->mappings[i].sockfd, &fdset)) {
continue;
}
UA_StatusCode retval = socket_recv(layer->mappings[i].connection, &buf, 0);
if(retval == UA_STATUSCODE_GOOD) {
js[j].job.binaryMessage.connection = layer->mappings[i].connection;
js[j].job.binaryMessage.message = buf;
js[j].type = UA_JOBTYPE_BINARYMESSAGE_NETWORKLAYER;
j++;
} else if (retval == UA_STATUSCODE_BADCONNECTIONCLOSED) {
UA_Connection *c = layer->mappings[i].connection;
/* the socket was closed from remote */
js[j].type = UA_JOBTYPE_DETACHCONNECTION;
js[j].job.closeConnection = layer->mappings[i].connection;
layer->mappings[i] = layer->mappings[layer->mappingsSize-1];
layer->mappingsSize--;
j++;
js[j].type = UA_JOBTYPE_METHODCALL_DELAYED;
js[j].job.methodCall.method = FreeConnectionCallback;
js[j].job.methodCall.data = c;
j++;
}
}
if(j == 0) {
free(js);
js = NULL;
}
*jobs = js;
return j;
}
static size_t
ServerNetworkLayerTCP_stop(UA_ServerNetworkLayer *nl, UA_Job **jobs) {
ServerNetworkLayerTCP *layer = nl->handle;
UA_LOG_INFO(layer->logger, UA_LOGCATEGORY_NETWORK,
"Shutting down the TCP network layer with %d open connection(s)", layer->mappingsSize);
shutdown(layer->serversockfd,2);
CLOSESOCKET(layer->serversockfd);
UA_Job *items = malloc(sizeof(UA_Job) * layer->mappingsSize * 2);
if(!items)
return 0;
for(size_t i = 0; i < layer->mappingsSize; i++) {
socket_close(layer->mappings[i].connection);
items[i*2].type = UA_JOBTYPE_DETACHCONNECTION;
items[i*2].job.closeConnection = layer->mappings[i].connection;
items[(i*2)+1].type = UA_JOBTYPE_METHODCALL_DELAYED;
items[(i*2)+1].job.methodCall.method = FreeConnectionCallback;
items[(i*2)+1].job.methodCall.data = layer->mappings[i].connection;
}
#ifdef _WIN32
WSACleanup();
#endif
*jobs = items;
return layer->mappingsSize*2;
}
/* run only when the server is stopped */
static void ServerNetworkLayerTCP_deleteMembers(UA_ServerNetworkLayer *nl) {
ServerNetworkLayerTCP *layer = nl->handle;
free(layer->mappings);
free(layer);
UA_String_deleteMembers(&nl->discoveryUrl);
}
UA_ServerNetworkLayer
UA_ServerNetworkLayerTCP(UA_ConnectionConfig conf, UA_UInt16 port) {
#ifdef _WIN32
WORD wVersionRequested;
WSADATA wsaData;
wVersionRequested = MAKEWORD(2, 2);
WSAStartup(wVersionRequested, &wsaData);
#endif
UA_ServerNetworkLayer nl;
memset(&nl, 0, sizeof(UA_ServerNetworkLayer));
ServerNetworkLayerTCP *layer = calloc(1,sizeof(ServerNetworkLayerTCP));
if(!layer)
return nl;
layer->conf = conf;
layer->port = port;
nl.handle = layer;
nl.start = ServerNetworkLayerTCP_start;
nl.getJobs = ServerNetworkLayerTCP_getJobs;
nl.stop = ServerNetworkLayerTCP_stop;
nl.deleteMembers = ServerNetworkLayerTCP_deleteMembers;
return nl;
}
/***************************/
/* Client NetworkLayer TCP */
/***************************/
static UA_StatusCode
ClientNetworkLayerGetBuffer(UA_Connection *connection, size_t length, UA_ByteString *buf) {
if(length > connection->remoteConf.recvBufferSize)
return UA_STATUSCODE_BADCOMMUNICATIONERROR;
if(connection->state == UA_CONNECTION_CLOSED)
return UA_STATUSCODE_BADCONNECTIONCLOSED;
return UA_ByteString_allocBuffer(buf, connection->remoteConf.recvBufferSize);
}
static void
ClientNetworkLayerReleaseBuffer(UA_Connection *connection, UA_ByteString *buf) {
UA_ByteString_deleteMembers(buf);
}
static void
ClientNetworkLayerClose(UA_Connection *connection) {
#ifdef UA_ENABLE_MULTITHREADING
if(uatomic_xchg(&connection->state, UA_CONNECTION_CLOSED) == UA_CONNECTION_CLOSED)
return;
#else
if(connection->state == UA_CONNECTION_CLOSED)
return;
connection->state = UA_CONNECTION_CLOSED;
#endif
socket_close(connection);
}
/* we have no networklayer. instead, attach the reusable buffer to the handle */
UA_Connection
UA_ClientConnectionTCP(UA_ConnectionConfig localConf, const char *endpointUrl, UA_Logger logger) {
UA_Connection connection;
UA_Connection_init(&connection);
connection.localConf = localConf;
//socket_set_nonblocking(connection.sockfd);
connection.send = socket_write;
connection.recv = socket_recv;
connection.close = ClientNetworkLayerClose;
connection.getSendBuffer = ClientNetworkLayerGetBuffer;
connection.releaseSendBuffer = ClientNetworkLayerReleaseBuffer;
connection.releaseRecvBuffer = ClientNetworkLayerReleaseBuffer;
size_t urlLength = strlen(endpointUrl);
if(urlLength < 11 || urlLength >= 512) {
UA_LOG_WARNING((*logger), UA_LOGCATEGORY_NETWORK, "Server url size invalid");
return connection;
}
if(strncmp(endpointUrl, "opc.tcp://", 10) != 0) {
UA_LOG_WARNING((*logger), UA_LOGCATEGORY_NETWORK, "Server url does not begin with opc.tcp://");
return connection;
}
UA_UInt16 portpos = 9;
UA_UInt16 port;
for(port = 0; portpos < urlLength-1; portpos++) {
if(endpointUrl[portpos] == ':') {
char *endPtr = NULL;
unsigned long int tempulong = strtoul(&endpointUrl[portpos+1], &endPtr, 10);
if (ERANGE != errno && tempulong < UINT16_MAX && endPtr != &endpointUrl[portpos+1])
port = (UA_UInt16)tempulong;
break;
}
}
if(port == 0) {
UA_LOG_WARNING((*logger), UA_LOGCATEGORY_NETWORK, "Port invalid");
return connection;
}
char hostname[512];
for(int i=10; i < portpos; i++)
hostname[i-10] = endpointUrl[i];
hostname[portpos-10] = 0;
#ifdef _WIN32
WORD wVersionRequested;
WSADATA wsaData;
wVersionRequested = MAKEWORD(2, 2);
WSAStartup(wVersionRequested, &wsaData);
if((connection.sockfd = socket(PF_INET, SOCK_STREAM,0)) == (UA_Int32)INVALID_SOCKET) {
#else
if((connection.sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
#endif
UA_LOG_WARNING((*logger), UA_LOGCATEGORY_NETWORK, "Could not create socket");
return connection;
}
struct hostent *server = gethostbyname(hostname);
if(!server) {
UA_LOG_WARNING((*logger), UA_LOGCATEGORY_NETWORK, "DNS lookup of %s failed", hostname);
return connection;
}
struct sockaddr_in server_addr;
memset(&server_addr, 0, sizeof(server_addr));
memcpy((char *)&server_addr.sin_addr.s_addr, (char *)server->h_addr_list[0], (size_t)server->h_length);
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(port);
connection.state = UA_CONNECTION_OPENING;
if(connect(connection.sockfd, (struct sockaddr *) &server_addr, sizeof(server_addr)) < 0) {
ClientNetworkLayerClose(&connection);
UA_LOG_WARNING((*logger), UA_LOGCATEGORY_NETWORK, "Connection failed");
return connection;
}
#ifdef SO_NOSIGPIPE
int val = 1;
if(setsockopt(connection.sockfd, SOL_SOCKET, SO_NOSIGPIPE, (void*)&val, sizeof(val)) < 0) {
UA_LOG_WARNING((*logger), UA_LOGCATEGORY_NETWORK, "Couldn't set SO_NOSIGPIPE");
return connection;
}
#endif
return connection;
}
/*********************************** amalgamated original file "/home/wn/Sources/open62541-open62541-395ce48/plugins/logger_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.
*/
#include <stdio.h>
#include <stdarg.h>
const char *LogLevelNames[6] = {"trace", "debug", "info", "warning", "error", "fatal"};
const char *LogCategoryNames[6] = {"network", "channel", "session", "server", "client", "userland"};
#if ((__GNUC__ == 4 && __GNUC_MINOR__ >= 6) || __GNUC__ > 4 || defined(__clang__))
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wformat-nonliteral"
#endif
void Logger_Stdout(UA_LogLevel level, UA_LogCategory category, const char *msg, ...) {
UA_String t = UA_DateTime_toString(UA_DateTime_now());
printf("[%.23s] %s/%s\t", t.data, LogLevelNames[level], LogCategoryNames[category]);
UA_ByteString_deleteMembers(&t);
va_list ap;
va_start(ap, msg);
vprintf(msg, ap);
va_end(ap);
printf("\n");
}
#if ((__GNUC__ == 4 && __GNUC_MINOR__ >= 6) || __GNUC__ > 4 || defined(__clang__))
#pragma GCC diagnostic pop
#endif
/*********************************** amalgamated original file "/home/wn/Sources/open62541-open62541-395ce48/plugins/ua_config_standard.c" ***********************************/
#define MANUFACTURER_NAME "open62541.org"
#define PRODUCT_NAME "open62541 OPC UA Server"
#define PRODUCT_URI "urn:unconfigured:open62541"
#define APPLICATION_NAME "open62541-based OPC UA Application"
#define APPLICATION_URI "urn:unconfigured:application"
#define UA_STRING_STATIC(s) {sizeof(s)-1, (UA_Byte*)s}
#define UA_STRING_STATIC_NULL {0, NULL}
UA_UsernamePasswordLogin usernamePasswords[2] = {
{ UA_STRING_STATIC("user1"), UA_STRING_STATIC("password") },
{ UA_STRING_STATIC("user2"), UA_STRING_STATIC("password1") } };
const UA_ServerConfig UA_ServerConfig_standard = {
.nThreads = 1,
.logger = Logger_Stdout,
.buildInfo = {
.productUri = UA_STRING_STATIC(PRODUCT_URI),
.manufacturerName = UA_STRING_STATIC(MANUFACTURER_NAME),
.productName = UA_STRING_STATIC(PRODUCT_NAME),
.softwareVersion = UA_STRING_STATIC("0"),
.buildNumber = UA_STRING_STATIC("0"),
.buildDate = 0 },
.applicationDescription = {
.applicationUri = UA_STRING_STATIC(APPLICATION_URI),
.productUri = UA_STRING_STATIC(PRODUCT_URI),
.applicationName = { .locale = UA_STRING_STATIC(""),
.text = UA_STRING_STATIC(APPLICATION_NAME) },
.applicationType = UA_APPLICATIONTYPE_SERVER,
.gatewayServerUri = UA_STRING_STATIC_NULL,
.discoveryProfileUri = UA_STRING_STATIC_NULL,
.discoveryUrlsSize = 0,
.discoveryUrls = NULL },
.serverCertificate = UA_STRING_STATIC_NULL,
.networkLayersSize = 0,
.networkLayers = NULL,
.enableAnonymousLogin = true,
.enableUsernamePasswordLogin = true,
.usernamePasswordLogins = usernamePasswords,
.usernamePasswordLoginsSize = 2,
.publishingIntervalLimits = { .min = 100.0, .max = 3600.0 * 1000.0 },
.lifeTimeCountLimits = { .max = 15000, .min = 3 },
.keepAliveCountLimits = { .max = 100, .min = 1 },
.maxNotificationsPerPublish = 1000,
.samplingIntervalLimits = { .min = 50.0, .max = 24.0 * 3600.0 * 1000.0 },
.queueSizeLimits = { .max = 100, .min = 1 }
};
const UA_EXPORT UA_ClientConfig UA_ClientConfig_standard = {
.timeout = 5000,
.secureChannelLifeTime = 600000,
.logger = Logger_Stdout,
.localConnectionConfig = {
.protocolVersion = 0,
.sendBufferSize = 65536,
.recvBufferSize = 65536,
.maxMessageSize = 65536,
.maxChunkCount = 1 },
.connectionFunc = UA_ClientConnectionTCP
};
/*********************************** amalgamated original file "/home/wn/Sources/open62541-open62541-395ce48/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
*/
/* 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 tm *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/wn/Sources/open62541-open62541-395ce48/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
*/
/*
* This code is derived from the full C implementation, which is in turn
* derived from the canonical C++ PCG implementation. The C++ version
* has many additional features and is preferable if you can use C++ in
* your project.
*/
// state for global RNGs
static pcg32_random_t pcg32_global = PCG32_INITIALIZER;
// pcg32_srandom(initial_state, initseq)
// pcg32_srandom_r(rng, initial_state, initseq):
// Seed the rng. Specified in two parts, state initializer and a
// sequence selection constant (a.k.a. stream id)
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);
}
void pcg32_srandom(uint64_t seed, uint64_t seq)
{
pcg32_srandom_r(&pcg32_global, seed, seq);
}
// pcg32_random()
// pcg32_random_r(rng)
// Generate a uniformly distributed 32-bit random number
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) & 31));
}
uint32_t pcg32_random()
{
return pcg32_random_r(&pcg32_global);
}
// pcg32_boundedrand(bound):
// pcg32_boundedrand_r(rng, bound):
// Generate a uniformly distributed number, r, where 0 <= r < bound
uint32_t pcg32_boundedrand_r(pcg32_random_t* rng, uint32_t bound)
{
// To avoid bias, we need to make the range of the RNG a multiple of
// bound, which we do by dropping output less than a threshold.
// A naive scheme to calculate the threshold would be to do
//
// uint32_t threshold = 0x100000000ull % bound;
//
// but 64-bit div/mod is slower than 32-bit div/mod (especially on
// 32-bit platforms). In essence, we do
//
// uint32_t threshold = (0x100000000ull-bound) % bound;
//
// because this version will calculate the same modulus, but the LHS
// value is less than 2^32.
uint32_t threshold = -bound % bound;
// Uniformity guarantees that this loop will terminate. In practice, it
// should usually terminate quickly; on average (assuming all bounds are
// equally likely), 82.25% of the time, we can expect it to require just
// one iteration. In the worst case, someone passes a bound of 2^31 + 1
// (i.e., 2147483649), which invalidates almost 50% of the range. In
// practice, bounds are typically small and only a tiny amount of the range
// is eliminated.
for (;;) {
uint32_t r = pcg32_random_r(rng);
if (r >= threshold)
return r % bound;
}
}
uint32_t pcg32_boundedrand(uint32_t bound)
{
return pcg32_boundedrand_r(&pcg32_global, bound);
}