/* 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 * * 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 #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 #include int __secs_to_tm(long long t, struct tm *tm); /*********************************** amalgamated original file "/home/wn/Sources/open62541-open62541-395ce48/src/ua_util.h" ***********************************/ #include #define UA_assert(ignore) assert(ignore) /*********************/ /* Memory Management */ /*********************/ /* Replace the macros with functions for custom allocators if necessary */ #include // malloc, free #ifdef _WIN32 # include #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 # 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 //needed for amalgamation # include # undef SLIST_ENTRY #endif #include #if defined(_WIN32) && !defined(__MINGW32__) int gettimeofday(struct timeval *tp, struct timezone *tzp); #else # include #endif #if defined(__APPLE__) || defined(__MACH__) #include #include #endif /*************************/ /* External Dependencies */ /*************************/ #ifdef UA_ENABLE_MULTITHREADING # define _LGPL_SOURCE # include # include # include # include # include # 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_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 /* 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) & (uint64_t)((1LL< 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, ¤t->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;inamespacesSize;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, ¤tTime, &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;ivalue.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;ijobsSize;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(¤t->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(¤t->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 ¤t->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(¤t->session.authenticationToken, token)) break; } if(!current) return UA_STATUSCODE_BADSESSIONIDINVALID; LIST_REMOVE(current, pointers); UA_Session_deleteMembersCleanup(¤t->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 = ⦥ } 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;jexternalNamespacesSize;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 = ⦥ } /* 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 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; inodesToDeleteSize; 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;iendpointUri 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 // malloc, free #include // snprintf #include // memset #include #ifdef _WIN32 # include # include # include # define CLOSESOCKET(S) closesocket(S) # define ssize_t long #else # include # include # include # ifndef __CYGWIN__ # include # endif # include # include //gethostbyname for the client # include // read, write, close # include # ifdef __QNX__ # include # 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 #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 #include 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 * * 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); }